diff options
Diffstat (limited to 'openecomp-ui/src/sdc-app/onboarding/licenseModel')
67 files changed, 3033 insertions, 1736 deletions
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js index a851e77dc8..cc9d9c536d 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/FinalizedLicenseModelListReducer.js @@ -1,23 +1,18 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {actionTypes} from './LicenseModelConstants.js'; export default (state = [], action) => { diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js index ad91a0da65..e21b0a81b0 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModel.js @@ -1,30 +1,24 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {connect} from 'react-redux'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import {statusEnum as versionStatusEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js'; import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js'; import TabulatedEditor from 'src/nfvo-components/editor/TabulatedEditor.jsx'; - +import ActivityLogActionHelper from 'nfvo-components/activity-log/ActivityLogActionHelper.js'; import {enums} from 'sdc-app/onboarding/OnboardingConstants.js'; import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js'; @@ -45,6 +39,11 @@ const buildNavigationBarProps = (licenseModel, screen) => { name: vendorName, items: [ { + id: navigationItems.LICENSE_MODEL_OVERVIEW, + name: i18n('Overview'), + meta + }, + { id: navigationItems.LICENSE_AGREEMENTS, name: i18n('License Agreements'), meta @@ -63,15 +62,22 @@ const buildNavigationBarProps = (licenseModel, screen) => { id: navigationItems.LICENSE_KEY_GROUPS, name: i18n('License Key Groups'), meta + }, + { + id: navigationItems.ACTIVITY_LOG, + name: i18n('Activity Log'), + meta } ] }]; const activeItemId = ({ + [enums.SCREEN.LICENSE_MODEL_OVERVIEW]: navigationItems.LICENSE_MODEL_OVERVIEW, [enums.SCREEN.LICENSE_AGREEMENTS]: navigationItems.LICENSE_AGREEMENTS, [enums.SCREEN.FEATURE_GROUPS]: navigationItems.FEATURE_GROUPS, [enums.SCREEN.ENTITLEMENT_POOLS]: navigationItems.ENTITLEMENT_POOLS, - [enums.SCREEN.LICENSE_KEY_GROUPS]: navigationItems.LICENSE_KEY_GROUPS + [enums.SCREEN.LICENSE_KEY_GROUPS]: navigationItems.LICENSE_KEY_GROUPS, + [enums.SCREEN.ACTIVITY_LOG]: navigationItems.ACTIVITY_LOG })[screen]; return { @@ -82,9 +88,7 @@ const buildNavigationBarProps = (licenseModel, screen) => { const buildVersionControllerProps = (licenseModel) => { let {version, viewableVersions, status: currentStatus, lockingUser} = licenseModel; - let {status, isCheckedOut} = (currentStatus === versionStatusEnum.CHECK_OUT_STATUS) ? - VersionControllerUtils.getCheckOutStatusKindByUserID(currentStatus, lockingUser) : - {status: currentStatus, isCheckedOut: false}; + let {status, isCheckedOut} = VersionControllerUtils.getCheckOutStatusKindByUserID(currentStatus, lockingUser); return { version, @@ -104,29 +108,46 @@ const mapStateToProps = ({licenseModel: {licenseModelEditor}}, {currentScreen: { const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {licenseModelId}}}) => { + return { - onVersionControllerAction: action => - LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action}).then(() => { + onVersionControllerAction: (action, version) => + LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action, version}).then((newVersion) => { switch(screen) { + case enums.SCREEN.LICENSE_MODEL_OVERVIEW: + /** + * TODO change to specific rest + */ + LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version: newVersion}); + break; case enums.SCREEN.LICENSE_AGREEMENTS: - LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId}); + LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version: newVersion}); break; case enums.SCREEN.FEATURE_GROUPS: - FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId}); + FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version: newVersion}); break; case enums.SCREEN.ENTITLEMENT_POOLS: - EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId}); + EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version: newVersion}); break; case enums.SCREEN.LICENSE_KEY_GROUPS: - LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId}); + LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version: newVersion}); + break; + case enums.SCREEN.ACTIVITY_LOG: + ActivityLogActionHelper.fetchActivityLog(dispatch, {itemId: licenseModelId, versionId: newVersion.id}); break; } }), - onVersionSwitching: version => LicenseAgreementActionHelper.switchVersion(dispatch, {licenseModelId, version}), - onClose: () => OnboardingActionHelper.navigateToOnboardingCatalog(dispatch), + onVersionSwitching: version => { + LicenseModelActionHelper.switchVersion(dispatch, {licenseModelId, version}); + if(screen === enums.SCREEN.ACTIVITY_LOG) { + ActivityLogActionHelper.fetchActivityLog(dispatch, {itemId: licenseModelId, versionId: version.id}); + } + }, onNavigate: ({id, meta: {version}}) => { switch(id) { + case navigationItems.LICENSE_MODEL_OVERVIEW: + OnboardingActionHelper.navigateToLicenseModelOverview(dispatch, {licenseModelId, version}); + break; case navigationItems.LICENSE_AGREEMENTS: OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId, version}); break; @@ -139,6 +160,9 @@ const mapActionsToProps = (dispatch, {currentScreen: {screen, props: {licenseMod case navigationItems.LICENSE_KEY_GROUPS: OnboardingActionHelper.navigateToLicenseKeyGroups(dispatch, {licenseModelId, version}); break; + case navigationItems.ACTIVITY_LOG: + OnboardingActionHelper.navigateToLicenseModelActivityLog(dispatch, {licenseModelId, version}); + break; } } }; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js index a379a2c40f..186f1cbc7b 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js @@ -1,29 +1,28 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; import {actionTypes} from './LicenseModelConstants.js'; +import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; import {actionsEnum as vcActionsEnum} from 'nfvo-components/panel/versionController/VersionControllerConstants.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import NotificationConstants from 'nfvo-components/notifications/NotificationConstants.js'; +import LicenseAgreementActionHelper from './licenseAgreement/LicenseAgreementActionHelper.js'; +import FeatureGroupsActionHelper from './featureGroups/FeatureGroupsActionHelper.js'; +import EntitlementPoolsActionHelper from './entitlementPools/EntitlementPoolsActionHelper.js'; +import LicenseKeyGroupsActionHelper from './licenseKeyGroups/LicenseKeyGroupsActionHelper.js'; function baseUrl() { const restPrefix = Configuration.get('restPrefix'); @@ -39,12 +38,32 @@ function fetchFinalizedLicenseModels() { } function fetchLicenseModelById(licenseModelId, version) { - let versionQuery = version ? `?version=${version}` : ''; - return RestAPIUtil.fetch(`${baseUrl()}${licenseModelId}${versionQuery}`); + const {id: versionId} = version; + return RestAPIUtil.fetch(`${baseUrl()}${licenseModelId}/versions/${versionId}`); +} + +function putLicenseModelAction(id, action, version) { + const {id: versionId} = version; + return RestAPIUtil.put(`${baseUrl()}${id}/versions/${versionId}/actions`, {action: action}); +} + +function putLicenseModel(licenseModel) { + let {id, vendorName, description, iconRef, version: {id: versionId}} = licenseModel; + return RestAPIUtil.put(`${baseUrl()}${id}/versions/${versionId}`, { + vendorName, + description, + iconRef + }); +} + +function adjustMinorVersion(version, value) { + let ar = version.split('.'); + return ar[0] + '.' + (parseInt(ar[1]) + value); } -function putLicenseModelAction(id, action) { - return RestAPIUtil.save(`${baseUrl()}${id}/actions`, {action: action}); +function adjustMajorVersion(version, value) { + let ar = version.split('.'); + return (parseInt(ar[0]) + value) + '.0'; } const LicenseModelActionHelper = { @@ -67,13 +86,11 @@ const LicenseModelActionHelper = { }, fetchLicenseModelById(dispatch, {licenseModelId, version}) { - return fetchLicenseModelById(licenseModelId, version).then(response => { - if(version) { - response.version = version; - } + + return fetchLicenseModelById(licenseModelId, version).then(response => { dispatch({ type: actionTypes.LICENSE_MODEL_LOADED, - response + response: {...response, version} }); }); }, @@ -85,17 +102,68 @@ const LicenseModelActionHelper = { }); }, - performVCAction(dispatch, {licenseModelId, action}) { - return putLicenseModelAction(licenseModelId, action).then(() => { + fetchLicenseModelItems(dispatch, {licenseModelId, version}) { + return Promise.all([ + LicenseAgreementActionHelper.fetchLicenseAgreementList(dispatch, {licenseModelId, version}), + FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version}), + EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version}), + LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version}) + ]); + }, + + performVCAction(dispatch, {licenseModelId, action, version}) { + return putLicenseModelAction(licenseModelId, action, version).then(() => { if(action === vcActionsEnum.SUBMIT){ dispatch({ - type: NotificationConstants.NOTIFY_SUCCESS, - data: {title: i18n('Submit Succeeded'), msg: i18n('This license model successfully submitted'), timeout: 2000} + type: modalActionTypes.GLOBAL_MODAL_SUCCESS, + data: { + title: i18n('Submit Succeeded'), + msg: i18n('This license model successfully submitted'), + cancelButtonText: i18n('OK'), + timeout: 2000 + } }); } - return LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId}); + + let newVersionId = version.id; + /* + TODO Temorary switch to change version label + */ + switch(action) { + case vcActionsEnum.CHECK_OUT: + newVersionId = adjustMinorVersion(version.label, 1); + break; + case vcActionsEnum.UNDO_CHECK_OUT: + newVersionId = adjustMinorVersion(version.label, -1); + break; + case vcActionsEnum.SUBMIT: + newVersionId = adjustMajorVersion(version.label, 1); + } + + LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version:{id: newVersionId, label: newVersionId}}); + return Promise.resolve({id: newVersionId, label: newVersionId}); + }); + }, + + switchVersion(dispatch, {licenseModelId, version}) { + LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version: {id: version.id, label: version.label}}).then(() => { + LicenseModelActionHelper.fetchLicenseModelItems(dispatch, {licenseModelId, version}); + }); + }, + + saveLicenseModel(dispatch, {licenseModel}) { + return putLicenseModel(licenseModel).then(() => { + dispatch({ + type: actionTypes.ADD_LICENSE_MODEL, + licenseModel + }); + dispatch({ + type: actionTypes.LICENSE_MODEL_LOADED, + response: licenseModel + }); }); } + }; export default LicenseModelActionHelper; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js index 13fa9f5284..4ba10c3a68 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js @@ -1,23 +1,18 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ @@ -29,8 +24,10 @@ export const actionTypes = keyMirror({ }); export const navigationItems = keyMirror({ - LICENSE_AGREEMENTS: 'License Agreements', - FEATURE_GROUPS: 'Feature Groups', - ENTITLEMENT_POOLS: 'Entitlement Pools', - LICENSE_KEY_GROUPS: 'License Key Groups' + LICENSE_MODEL_OVERVIEW: 'overview', + LICENSE_AGREEMENTS: 'license-agreements', + FEATURE_GROUPS: 'feature-groups', + ENTITLEMENT_POOLS: 'entitlement-pools', + LICENSE_KEY_GROUPS: 'license-key-groups', + ACTIVITY_LOG: 'activity-log' }); diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js index e92e32aa9e..add5ac6a98 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelEditorReducer.js @@ -1,28 +1,23 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {actionTypes} from './LicenseModelConstants.js'; export default (state = {}, action) => { switch (action.type) { - case actionTypes.LICENSE_MODEL_LOADED: + case actionTypes.LICENSE_MODEL_LOADED: return { ...state, data: action.response diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js index 8874c4ce21..fd73b462a3 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelListReducer.js @@ -1,23 +1,18 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {actionTypes} from './LicenseModelConstants.js'; export default (state = [], action) => { diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js index 5982b9f8ab..9a2d114bdc 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js @@ -1,66 +1,85 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {combineReducers} from 'redux'; +import activityLogReducer from 'nfvo-components/activity-log/ActivityLogReducer.js'; + import licenseModelCreationReducer from './creation/LicenseModelCreationReducer.js'; import licenseModelEditorReducer from './LicenseModelEditorReducer.js'; import licenseAgreementListReducer from './licenseAgreement/LicenseAgreementListReducer.js'; import licenseAgreementEditorReducer from './licenseAgreement/LicenseAgreementEditorReducer.js'; -import {actionTypes as licenseAgreementActionTypes} from './licenseAgreement/LicenseAgreementConstants.js'; import featureGroupsEditorReducer from './featureGroups/FeatureGroupsEditorReducer.js'; import featureGroupsListReducer from './featureGroups/FeatureGroupsListReducer.js'; -import {actionTypes as featureGroupsActionConstants} from './featureGroups/FeatureGroupsConstants'; import entitlementPoolsListReducer from './entitlementPools/EntitlementPoolsListReducer.js'; import entitlementPoolsEditorReducer from './entitlementPools/EntitlementPoolsEditorReducer.js'; -import {actionTypes as entitlementPoolsConstants} from './entitlementPools/EntitlementPoolsConstants'; import licenseKeyGroupsEditorReducer from './licenseKeyGroups/LicenseKeyGroupsEditorReducer.js'; import licenseKeyGroupsListReducer from './licenseKeyGroups/LicenseKeyGroupsListReducer.js'; -import {actionTypes as licenseKeyGroupsConstants} from './licenseKeyGroups/LicenseKeyGroupsConstants.js'; + +import {createPlainDataReducer} from 'sdc-app/common/reducers/PlainDataReducer.js'; + +import {actionTypes as licenseModelOverviewConstants, selectedButton, VLM_DESCRIPTION_FORM} from './overview/LicenseModelOverviewConstants.js'; export default combineReducers({ - licenseModelCreation: licenseModelCreationReducer, + licenseModelCreation: createPlainDataReducer(licenseModelCreationReducer), licenseModelEditor: licenseModelEditorReducer, licenseAgreement: combineReducers({ - licenseAgreementEditor: licenseAgreementEditorReducer, - licenseAgreementList: licenseAgreementListReducer, - licenseAgreementToDelete: (state = false, action) => action.type === licenseAgreementActionTypes.LICENSE_AGREEMENT_DELETE_CONFIRM ? action.licenseAgreementToDelete : state + licenseAgreementEditor: createPlainDataReducer(licenseAgreementEditorReducer), + licenseAgreementList: licenseAgreementListReducer }), featureGroup: combineReducers({ - featureGroupEditor: featureGroupsEditorReducer, - featureGroupsList: featureGroupsListReducer, - featureGroupToDelete: (state = false, action) => action.type === featureGroupsActionConstants.FEATURE_GROUPS_DELETE_CONFIRM ? action.featureGroupToDelete : state + featureGroupEditor: createPlainDataReducer(featureGroupsEditorReducer), + featureGroupsList: featureGroupsListReducer }), entitlementPool: combineReducers({ - entitlementPoolEditor: entitlementPoolsEditorReducer, - entitlementPoolsList: entitlementPoolsListReducer, - entitlementPoolToDelete: (state = false, action) => action.type === entitlementPoolsConstants.ENTITLEMENT_POOLS_DELETE_CONFIRM ? action.entitlementPoolToDelete : state + entitlementPoolEditor: createPlainDataReducer(entitlementPoolsEditorReducer), + entitlementPoolsList: entitlementPoolsListReducer }), licenseKeyGroup: combineReducers({ - licenseKeyGroupsEditor: licenseKeyGroupsEditorReducer, - licenseKeyGroupsList: licenseKeyGroupsListReducer, - licenseKeyGroupToDelete: (state = false, action) => action.type === licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM ? action.licenseKeyGroupToDelete : state + licenseKeyGroupsEditor: createPlainDataReducer(licenseKeyGroupsEditorReducer), + licenseKeyGroupsList: licenseKeyGroupsListReducer }), + licenseModelOverview: combineReducers({ + selectedTab: (state = selectedButton.VLM_LIST_VIEW, action) => action.type === licenseModelOverviewConstants.LICENSE_MODEL_OVERVIEW_TAB_SELECTED ? action.buttonTab : state, + descriptionEditor: createPlainDataReducer(function(state = false, action) { + if (action.type === licenseModelOverviewConstants.LM_DATA_CHANGED) { + return { + ...state, + data : { + description : action.description + }, + formReady: null, + formName: VLM_DESCRIPTION_FORM, + genericFieldInfo: { + 'description': { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}] + } + } + }; + //return action.description; + } else { + return state; + } + } + )}), + activityLog: activityLogReducer }); diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js index 63d0f27b6a..d85618c85f 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js @@ -1,40 +1,50 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {connect} from 'react-redux'; import OnboardingActionHelper from 'sdc-app/onboarding/OnboardingActionHelper.js'; import LicenseModelCreationActionHelper from './LicenseModelCreationActionHelper.js'; import LicenseModelCreationView from './LicenseModelCreationView.jsx'; +import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; +import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js'; + +export const mapStateToProps = ({licenseModelList, licenseModel: {licenseModelCreation}}) => { + let {genericFieldInfo} = licenseModelCreation; + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); -const mapStateToProps = ({licenseModel: {licenseModelCreation}}) => licenseModelCreation; + let VLMNames = {}; + for (let i = 0; i < licenseModelList.length; i++) { + VLMNames[licenseModelList[i].vendorName] = licenseModelList[i].id; + } + + return {...licenseModelCreation, isFormValid: isFormValid, VLMNames}; +}; -const mapActionsToProps = (dispatch) => { +export const mapActionsToProps = (dispatch) => { return { - onDataChanged: deltaData => LicenseModelCreationActionHelper.dataChanged(dispatch, {deltaData}), + onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}), onCancel: () => LicenseModelCreationActionHelper.close(dispatch), onSubmit: (licenseModel) => { LicenseModelCreationActionHelper.close(dispatch); - LicenseModelCreationActionHelper.createLicenseModel(dispatch, {licenseModel}).then(licenseModelId => { - OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId}); + LicenseModelCreationActionHelper.createLicenseModel(dispatch, {licenseModel}).then(response => { + LicenseModelActionHelper.fetchLicenseModels(dispatch).then(() => { + OnboardingActionHelper.navigateToLicenseModelOverview(dispatch, {licenseModelId: response.value}); + }); }); - } + }, + onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName) }; }; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js index c2a0409bd2..51f5b7f276 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationActionHelper.js @@ -1,27 +1,24 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; -import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js'; import {actionTypes} from './LicenseModelCreationConstants.js'; +import {modalContentMapper} from 'sdc-app/common/modal/ModalContentMapper.js'; +import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js'; +import i18n from 'nfvo-utils/i18n/i18n.js'; function baseUrl() { const restPrefix = Configuration.get('restPrefix'); @@ -29,7 +26,7 @@ function baseUrl() { } function createLicenseModel(licenseModel) { - return RestAPIUtil.create(baseUrl(), { + return RestAPIUtil.post(baseUrl(), { vendorName: licenseModel.vendorName, description: licenseModel.description, iconRef: 'icon' @@ -43,30 +40,28 @@ export default { dispatch({ type: actionTypes.OPEN }); + + dispatch({ + type: modalActionTypes.GLOBAL_MODAL_SHOW, + data: { + modalComponentName: modalContentMapper.LICENSE_MODEL_CREATION, + title: i18n('New License Model') + } + }); }, close(dispatch){ dispatch({ type: actionTypes.CLOSE }); - }, - dataChanged(dispatch, {deltaData}){ dispatch({ - type: actionTypes.DATA_CHANGED, - deltaData + type: modalActionTypes.GLOBAL_MODAL_CLOSE }); }, createLicenseModel(dispatch, {licenseModel}){ - return createLicenseModel(licenseModel).then(response => { - LicenseModelActionHelper.addLicenseModel(dispatch, { - licenseModel: { - ...licenseModel, - id: response.value - } - }); - return response.value; - }); + return createLicenseModel(licenseModel); } + }; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js index 603d177048..28f1175676 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationConstants.js @@ -1,27 +1,23 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ OPEN: null, - CLOSE: null, - DATA_CHANGED: null + CLOSE: null }); + +export const LICENSE_MODEL_CREATION_FORM_NAME = 'LMCREATIONFORM'; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js index a54d1b3089..879d356de2 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js @@ -1,42 +1,43 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - -import {actionTypes} from './LicenseModelCreationConstants.js'; +import {actionTypes, LICENSE_MODEL_CREATION_FORM_NAME} from './LicenseModelCreationConstants.js'; export default (state = {}, action) => { switch (action.type) { case actionTypes.OPEN: return { ...state, - data: {} + formReady: null, + formName: LICENSE_MODEL_CREATION_FORM_NAME, + data: {}, + genericFieldInfo: { + 'description' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}] + }, + 'vendorName' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 25}] + } + } }; case actionTypes.CLOSE: return {}; - case actionTypes.DATA_CHANGED: - return { - ...state, - data: { - ...state.data, - ...action.deltaData - } - }; default: return state; } diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx index 4dccc9e1c4..80040460c0 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx @@ -1,7 +1,24 @@ +/*! + * 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. + */ import React from 'react'; import i18n from 'nfvo-utils/i18n/i18n.js'; -import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx'; -import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx'; +import Validator from 'nfvo-utils/Validator.js'; +import Input from 'nfvo-components/input/validation/Input.jsx'; +import Form from 'nfvo-components/input/validation/Form.jsx'; +import {LICENSE_MODEL_CREATION_FORM_NAME} from './LicenseModelCreationConstants.js'; const LicenseModelPropType = React.PropTypes.shape({ id: React.PropTypes.string, @@ -13,39 +30,49 @@ class LicenseModelCreationView extends React.Component { static propTypes = { data: LicenseModelPropType, + VLMNames: React.PropTypes.object, onDataChanged: React.PropTypes.func.isRequired, onSubmit: React.PropTypes.func.isRequired, + onValidateForm: React.PropTypes.func.isRequired, onCancel: React.PropTypes.func.isRequired }; render() { - let {data = {}, onDataChanged} = this.props; + let {data = {}, onDataChanged, genericFieldInfo} = this.props; let {vendorName, description} = data; return ( <div> - <ValidationForm + {genericFieldInfo && <Form ref='validationForm' hasButtons={true} onSubmit={ () => this.submit() } onReset={ () => this.props.onCancel() } - labledButtons={true}> - <ValidationInput + labledButtons={true} + isValid={this.props.isFormValid} + formReady={this.props.formReady} + onValidateForm={() => this.validate() }> + <Input value={vendorName} label={i18n('Vendor Name')} - ref='vendor-name' - onChange={vendorName => onDataChanged({vendorName})} - validations={{maxLength: 25, required: true}} + data-test-id='vendor-name' + onChange={vendorName => onDataChanged({vendorName}, LICENSE_MODEL_CREATION_FORM_NAME, {vendorName: name => this.validateName(name)})} + isValid={genericFieldInfo.vendorName.isValid} + errorText={genericFieldInfo.vendorName.errorText} type='text' + isRequired={true} className='field-section'/> - <ValidationInput + <Input + isRequired={true} value={description} label={i18n('Description')} - ref='description' - onChange={description => onDataChanged({description})} - validations={{maxLength: 1000, required: true}} + data-test-id='vendor-description' + overlayPos='bottom' + onChange={description => onDataChanged({description}, LICENSE_MODEL_CREATION_FORM_NAME)} + isValid={genericFieldInfo.description.isValid} + errorText={genericFieldInfo.description.errorText} type='textarea' className='field-section'/> - </ValidationForm> + </Form>} </div> ); } @@ -55,6 +82,18 @@ class LicenseModelCreationView extends React.Component { const {data:licenseModel} = this.props; this.props.onSubmit(licenseModel); } + + validateName(value) { + const {data: {id}, VLMNames} = this.props; + const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: VLMNames}); + + return !isExists ? {isValid: true, errorText: ''} : + {isValid: false, errorText: i18n('License model by the name \'' + value + '\' already exists. License model name must be unique')}; + } + + validate() { + this.props.onValidateForm(LICENSE_MODEL_CREATION_FORM_NAME); + } } export default LicenseModelCreationView; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js index 631597a5b0..fe95b034dd 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js @@ -1,40 +1,35 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - 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) { +function baseUrl(licenseModelId, version) { const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/entitlement-pools`; + const {id: versionId} = version; + return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/entitlement-pools`; } -function fetchEntitlementPoolsList(licenseModelId, version) { - let versionQuery = version ? `?version=${version}` : ''; - return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`); +function fetchEntitlementPoolsList(licenseModelId, version) { + return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`); } -function postEntitlementPool(licenseModelId, entitlementPool) { - return RestAPIUtil.create(baseUrl(licenseModelId), { +function postEntitlementPool(licenseModelId, entitlementPool, version) { + return RestAPIUtil.post(baseUrl(licenseModelId, version), { name: entitlementPool.name, description: entitlementPool.description, thresholdValue: entitlementPool.thresholdValue, @@ -49,8 +44,8 @@ function postEntitlementPool(licenseModelId, entitlementPool) { } -function putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool) { - return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${entitlementPool.id}`, { +function putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool, version) { + return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${entitlementPool.id}`, { name: entitlementPool.name, description: entitlementPool.description, thresholdValue: entitlementPool.thresholdValue, @@ -64,8 +59,8 @@ function putEntitlementPool(licenseModelId, previousEntitlementPool, entitlement }); } -function deleteEntitlementPool(licenseModelId, entitlementPoolId) { - return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${entitlementPoolId}`); +function deleteEntitlementPool(licenseModelId, entitlementPoolId, version) { + return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}`); } @@ -84,8 +79,8 @@ export default { }); }, - deleteEntitlementPool(dispatch, {licenseModelId, entitlementPoolId}) { - return deleteEntitlementPool(licenseModelId, entitlementPoolId).then(() => { + deleteEntitlementPool(dispatch, {licenseModelId, entitlementPoolId, version}) { + return deleteEntitlementPool(licenseModelId, entitlementPoolId, version).then(() => { dispatch({ type: entitlementPoolsActionTypes.DELETE_ENTITLEMENT_POOL, entitlementPoolId @@ -106,9 +101,9 @@ export default { }); }, - saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool}) { + saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool, version}) { if (previousEntitlementPool) { - return putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool).then(() => { + return putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool, version).then(() => { dispatch({ type: entitlementPoolsActionTypes.EDIT_ENTITLEMENT_POOL, entitlementPool @@ -116,11 +111,12 @@ export default { }); } else { - return postEntitlementPool(licenseModelId, entitlementPool).then(response => { + return postEntitlementPool(licenseModelId, entitlementPool, version).then(response => { dispatch({ type: entitlementPoolsActionTypes.ADD_ENTITLEMENT_POOL, entitlementPool: { ...entitlementPool, + referencingFeatureGroups: [], id: response.value } }); diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx deleted file mode 100644 index 04f038f5f0..0000000000 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConfirmationModal.jsx +++ /dev/null @@ -1,51 +0,0 @@ -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 index 8a855076f3..ba0b238b17 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js @@ -1,25 +1,21 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import keyMirror from 'nfvo-utils/KeyMirror.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; +import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx'; export const actionTypes = keyMirror({ @@ -27,7 +23,6 @@ export const actionTypes = keyMirror({ ADD_ENTITLEMENT_POOL: null, EDIT_ENTITLEMENT_POOL: null, DELETE_ENTITLEMENT_POOL: null, - ENTITLEMENT_POOLS_DELETE_CONFIRM: null, entitlementPoolsEditor: { OPEN: null, @@ -107,6 +102,14 @@ export const optionsInputValues = { ] }; +export const extractValue = (item) => { + if (item === undefined) {return '';} //TODO fix it later + return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : ''; +}; +export const extractUnits = (units) => { + if (units === undefined) {return '';} //TODO fix it later + return units === 'Absolute' ? '' : '%'; +}; - +export const SP_ENTITLEMENT_POOL_FORM = 'SPENTITLEMENTPOOL'; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js index d5bd07e929..f89cf8fbb5 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js @@ -1,52 +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 - * + * + * 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========================================================= + * 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. */ - import {connect} from 'react-redux'; import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js'; import EntitlementPoolsEditorView from './EntitlementPoolsEditorView.jsx'; +import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; const mapStateToProps = ({licenseModel: {entitlementPool}}) => { - let {data} = entitlementPool.entitlementPoolEditor; - - let previousData; + let {data, genericFieldInfo, formReady} = entitlementPool.entitlementPoolEditor; + + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); + + let previousData, EPNames = {}; const entitlementPoolId = data ? data.id : null; if(entitlementPoolId) { previousData = entitlementPool.entitlementPoolsList.find(entitlementPool => entitlementPool.id === entitlementPoolId); } + const list = entitlementPool.entitlementPoolsList; + for (let i = 0; i < list.length; i++) { + EPNames[list[i].name] = list[i].id; + } + return { data, - previousData + genericFieldInfo, + previousData, + isFormValid, + formReady, + EPNames }; }; -const mapActionsToProps = (dispatch, {licenseModelId}) => { +const mapActionsToProps = (dispatch, {licenseModelId, version}) => { return { - onDataChanged: deltaData => EntitlementPoolsActionHelper.entitlementPoolsEditorDataChanged(dispatch, {deltaData}), + onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}), onCancel: () => EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch), onSubmit: ({previousEntitlementPool, entitlementPool}) => { EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch); - EntitlementPoolsActionHelper.saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool}); - } + EntitlementPoolsActionHelper.saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool, version}); + }, + onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName) }; }; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js index 86e97ecf8d..db1a3a97ca 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js @@ -1,30 +1,79 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - -import {actionTypes, defaultState} from './EntitlementPoolsConstants.js'; +import {actionTypes, defaultState, SP_ENTITLEMENT_POOL_FORM} from './EntitlementPoolsConstants.js'; export default (state = {}, action) => { switch (action.type) { case actionTypes.entitlementPoolsEditor.OPEN: return { ...state, + formReady: null, + formName: SP_ENTITLEMENT_POOL_FORM, + genericFieldInfo: { + 'name' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}] + }, + 'description' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}] + }, + 'manufacturerReferenceNumber' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 100}] + }, + 'increments' : { + isValid: true, + errorText: '', + validations: [{type: 'maxLength', data: 120}] + }, + 'operationalScope' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}] + }, + 'thresholdUnits' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}] + }, + 'thresholdValue' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}] + }, + 'entitlementMetric' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}] + }, + 'aggregationFunction' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}] + }, + 'time' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}] + } + }, data: action.entitlementPool ? {...action.entitlementPool} : defaultState.ENTITLEMENT_POOLS_EDITOR_DATA }; case actionTypes.entitlementPoolsEditor.DATA_CHANGED: diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx index 77c5a12e03..d484437015 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx @@ -1,14 +1,31 @@ +/*! + * 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. + */ import React from 'react'; - import i18n from 'nfvo-utils/i18n/i18n.js'; +import Validator from 'nfvo-utils/Validator.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 Input from 'nfvo-components/input/validation/Input.jsx'; +import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx'; +import Form from 'nfvo-components/input/validation/Form.jsx'; +import GridSection from 'nfvo-components/grid/GridSection.jsx'; +import GridItem from 'nfvo-components/grid/GridItem.jsx'; +import {optionsInputValues as EntitlementPoolsOptionsInputValues, thresholdUnitType, SP_ENTITLEMENT_POOL_FORM} 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, @@ -33,11 +50,172 @@ const EntitlementPoolPropType = React.PropTypes.shape({ }) }); +const EntitlementPoolsFormContent = ({data, genericFieldInfo, onDataChanged, validateName, validateChoiceWithOther, validateTimeOtherValue, thresholdValueValidation}) => { + let { + name, description, manufacturerReferenceNumber, operationalScope , aggregationFunction, thresholdUnits, thresholdValue, + increments, time, entitlementMetric} = data; + + return ( + <GridSection> + <GridItem colSpan={2}> + <Input + onChange={name => onDataChanged({name}, SP_ENTITLEMENT_POOL_FORM, {name: validateName})} + isValid={genericFieldInfo.name.isValid} + isRequired={true} + errorText={genericFieldInfo.name.errorText} + label={i18n('Name')} + value={name} + data-test-id='create-ep-name' + type='text'/> + </GridItem> + <GridItem colSpan={2}> + <InputOptions + onInputChange={()=>{}} + isMultiSelect={true} + + isRequired={true} + onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}}, + SP_ENTITLEMENT_POOL_FORM, {operationalScope: validateChoiceWithOther})} + onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER], + other: operationalScope}}, SP_ENTITLEMENT_POOL_FORM, {operationalScope: validateChoiceWithOther})} + label={i18n('Operational Scope')} + data-test-id='create-ep-operational-scope' + type='select' + multiSelectedEnum={operationalScope && operationalScope.choices} + otherValue={operationalScope && operationalScope.other} + values={EntitlementPoolsOptionsInputValues.OPERATIONAL_SCOPE} + isValid={genericFieldInfo.operationalScope.isValid} + errorText={genericFieldInfo.operationalScope.errorText} /> + </GridItem> + <GridItem colSpan={2} stretch> + <Input + onChange={description => onDataChanged({description}, SP_ENTITLEMENT_POOL_FORM)} + isValid={genericFieldInfo.description.isValid} + errorText={genericFieldInfo.description.errorText} + label={i18n('Description')} + value={description} + isRequired={true} + data-test-id='create-ep-description' + type='textarea'/> + </GridItem> + <GridItem colSpan={2}> + <div className='threshold-section'> + <Input + isRequired={true} + onChange={e => { + // setting the unit to the correct value + const selectedIndex = e.target.selectedIndex; + const val = e.target.options[selectedIndex].value; + onDataChanged({thresholdUnits: val}, SP_ENTITLEMENT_POOL_FORM); + // TODO make sure that the value is valid too + onDataChanged({thresholdValue: thresholdValue}, SP_ENTITLEMENT_POOL_FORM,{thresholdValue : thresholdValueValidation});} + + } + value={thresholdUnits} + label={i18n('Threshold Units')} + data-test-id='create-ep-threshold-units' + isValid={genericFieldInfo.thresholdUnits.isValid} + errorText={genericFieldInfo.thresholdUnits.errorText} + groupClassName='bootstrap-input-options' + className='input-options-select' + type='select' > + {EntitlementPoolsOptionsInputValues.THRESHOLD_UNITS.map(mtype => + <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)} + </Input> + + <Input + className='entitlement-pools-form-row-threshold-value' + onChange={thresholdValue => onDataChanged({thresholdValue}, SP_ENTITLEMENT_POOL_FORM, + {thresholdValue : thresholdValueValidation})} + label={i18n('Threshold Value')} + isValid={genericFieldInfo.thresholdValue.isValid} + errorText={genericFieldInfo.thresholdValue.errorText} + data-test-id='create-ep-threshold-value' + value={thresholdValue} + isRequired={true} + type='text'/> + </div> + <InputOptions + onInputChange={()=>{}} + isMultiSelect={false} + isRequired={true} + onEnumChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: entitlementMetric, other: ''}}, + SP_ENTITLEMENT_POOL_FORM, {entitlementMetric: validateChoiceWithOther})} + onOtherChange={entitlementMetric => onDataChanged({entitlementMetric:{choice: optionInputOther.OTHER, + other: entitlementMetric}}, SP_ENTITLEMENT_POOL_FORM, {entitlementMetric: validateChoiceWithOther})} + label={i18n('Entitlement Metric')} + data-test-id='create-ep-entitlement-metric' + type='select' + required={true} + selectedEnum={entitlementMetric && entitlementMetric.choice} + otherValue={entitlementMetric && entitlementMetric.other} + values={EntitlementPoolsOptionsInputValues.ENTITLEMENT_METRIC} + isValid={genericFieldInfo.entitlementMetric.isValid} + errorText={genericFieldInfo.entitlementMetric.errorText} /> + <InputOptions + onInputChange={()=>{}} + isMultiSelect={false} + isRequired={true} + onEnumChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: aggregationFunction, other: ''}}, + SP_ENTITLEMENT_POOL_FORM, {aggregationFunction: validateChoiceWithOther})} + onOtherChange={aggregationFunction => onDataChanged({aggregationFunction:{choice: optionInputOther.OTHER, + other: aggregationFunction}}, SP_ENTITLEMENT_POOL_FORM, {aggregationFunction: validateChoiceWithOther})} + label={i18n('Aggregate Function')} + data-test-id='create-ep-aggregate-function' + type='select' + required={true} + selectedEnum={aggregationFunction && aggregationFunction.choice} + otherValue={aggregationFunction && aggregationFunction.other} + values={EntitlementPoolsOptionsInputValues.AGGREGATE_FUNCTION} + isValid={genericFieldInfo.aggregationFunction.isValid} + errorText={genericFieldInfo.aggregationFunction.errorText} /> + </GridItem> + <GridItem colSpan={2}> + <Input + onChange={manufacturerReferenceNumber => onDataChanged({manufacturerReferenceNumber}, SP_ENTITLEMENT_POOL_FORM)} + label={i18n('Manufacturer Reference Number')} + value={manufacturerReferenceNumber} + isRequired={true} + data-test-id='create-ep-reference-number' + type='text'/> + </GridItem> + <GridItem colSpan={2}> + <InputOptions + onInputChange={()=>{}} + isMultiSelect={false} + isRequired={true} + onEnumChange={time => onDataChanged({time:{choice: time, other: ''}}, + SP_ENTITLEMENT_POOL_FORM, {time: validateChoiceWithOther})} + onOtherChange={time => onDataChanged({time:{choice: optionInputOther.OTHER, + other: time}}, SP_ENTITLEMENT_POOL_FORM, {time: validateTimeOtherValue})} + label={i18n('Time')} + data-test-id='create-ep-time' + type='select' + required={true} + selectedEnum={time && time.choice} + otherValue={time && time.other} + values={EntitlementPoolsOptionsInputValues.TIME} + isValid={genericFieldInfo.time.isValid} + errorText={genericFieldInfo.time.errorText} /> + </GridItem> + <GridItem colSpan={2}> + <Input + onChange={increments => onDataChanged({increments}, SP_ENTITLEMENT_POOL_FORM)} + label={i18n('Increments')} + value={increments} + data-test-id='create-ep-increments' + type='text'/> + </GridItem> + </GridSection> + ); +}; + class EntitlementPoolsEditorView extends React.Component { static propTypes = { data: EntitlementPoolPropType, previousData: EntitlementPoolPropType, + EPNames: React.PropTypes.object, isReadOnlyMode: React.PropTypes.bool, onDataChanged: React.PropTypes.func.isRequired, onSubmit: React.PropTypes.func.isRequired, @@ -49,119 +227,88 @@ class EntitlementPoolsEditorView extends React.Component { }; 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}; + let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo} = this.props; + 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'/> + <div> + { + genericFieldInfo && <Form + ref='validationForm' + hasButtons={true} + onSubmit={ () => this.submit() } + onReset={ () => this.props.onCancel() } + labledButtons={true} + isReadOnlyMode={isReadOnlyMode} + isValid={this.props.isFormValid} + formReady={this.props.formReady} + onValidateForm={() => this.props.onValidateForm(SP_ENTITLEMENT_POOL_FORM) } + className='entitlement-pools-form'> + <EntitlementPoolsFormContent + data={data} + genericFieldInfo={genericFieldInfo} + onDataChanged={onDataChanged} + validateName={(value)=> this.validateName(value)} + validateTimeOtherValue ={(value)=> this.validateTimeOtherValue(value)} + validateChoiceWithOther={(value)=> this.validateChoiceWithOther(value)} + thresholdValueValidation={(value, state)=> this.thresholdValueValidation(value, state)}/> + </Form> + } + </div> + ); + } - <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}/> + submit() { + const {data: entitlementPool, previousData: previousEntitlementPool} = this.props; + this.props.onSubmit({entitlementPool, previousEntitlementPool}); + } - </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'> + validateName(value) { + const {data: {id}, EPNames} = this.props; + const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: EPNames}); - <ValidationInput - onChange={manufacturerReferenceNumber => onDataChanged({manufacturerReferenceNumber})} - label={i18n('Manufacturer Reference Number')} - value={manufacturerReferenceNumber} - validations={{maxLength: 100, required: true}} - type='text'/> + return !isExists ? {isValid: true, errorText: ''} : + {isValid: false, errorText: i18n('Entitlement pool by the name \'' + value + '\' already exists. Entitlement pool name must be unique')}; + } - <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'/> + validateTimeOtherValue(value) { + return Validator.validate('time', value.other, [{type: 'required', data: true}, {type: 'numeric', data: true}]); + } - </div> - </ValidationForm> - ); + validateChoiceWithOther(value) { + let chosen = value.choice; + // if we have an empty multiple select we have a problem since it's required + if (value.choices) { + if (value.choices.length === 0) { + return Validator.validate('field', '', [{type: 'required', data: true}]); + } else { + // continuing validation with the first chosen value in case we have the 'Other' field + chosen = value.choices[0]; + } + } + if (chosen !== optionInputOther.OTHER) { + return Validator.validate('field', chosen, [{type: 'required', data: true}]); + } else { // when 'Other' was chosen, validate other value + return Validator.validate('field', value.other, [{type: 'required', data: true}]); + } } - submit() { - const {data: entitlementPool, previousData: previousEntitlementPool} = this.props; - this.props.onSubmit({entitlementPool, previousEntitlementPool}); + thresholdValueValidation(value, state) { + + let unit = state.data.thresholdUnits; + if (unit === thresholdUnitType.PERCENTAGE) { + return Validator.validate('thresholdValue', value, [ + {type: 'required', data: true}, + {type: 'numeric', data: true}, + {type: 'maximum', data: 100}, + {type: 'minimum', data: 0}]); + } else { + return Validator.validate('thresholdValue', value, [ + {type: 'numeric', data: true}, + {type: 'required', data: true}]); + } } + } 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 index 4b21a2fea8..993ed48f2b 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js @@ -1,27 +1,24 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {connect} from 'react-redux'; +import i18n from 'nfvo-utils/i18n/i18n.js'; import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js'; -import EntitlementPoolsListEditorView from './EntitlementPoolsListEditorView.jsx'; +import EntitlementPoolsListEditorView, {generateConfirmationMsg} from './EntitlementPoolsListEditorView.jsx'; import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js'; +import {actionTypes as globalMoadlActions} from 'nfvo-components/modal/GlobalModalConstants.js'; const mapStateToProps = ({licenseModel: {entitlementPool, licenseModelEditor}}) => { let {entitlementPoolsList} = entitlementPool; @@ -39,13 +36,21 @@ const mapStateToProps = ({licenseModel: {entitlementPool, licenseModelEditor}}) }; }; -const mapActionsToProps = (dispatch, {licenseModelId}) => { +const mapActionsToProps = (dispatch, {licenseModelId, version}) => { return { onAddEntitlementPoolClick: () => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch), onEditEntitlementPoolClick: entitlementPool => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch, {entitlementPool}), - onDeleteEntitlementPool: entitlementPool => EntitlementPoolsActionHelper.openDeleteEntitlementPoolConfirm(dispatch, { - licenseModelId, - entitlementPool + onDeleteEntitlementPool: entitlementPool => dispatch({ + type: globalMoadlActions.GLOBAL_MODAL_WARNING, + data:{ + msg: generateConfirmationMsg(entitlementPool), + title: i18n('Warning'), + onConfirmed: ()=>EntitlementPoolsActionHelper.deleteEntitlementPool(dispatch, { + licenseModelId, + entitlementPoolId: entitlementPool.id, + version + }) + } }) }; }; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx index 52df102503..07a6f21a1a 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx @@ -1,3 +1,18 @@ +/*! + * 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. + */ import React from 'react'; import i18n from 'nfvo-utils/i18n/i18n.js'; @@ -6,10 +21,7 @@ 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'; - +import {extractUnits, extractValue} from './EntitlementPoolsConstants'; class EntitlementPoolsListEditorView extends React.Component { static propTypes = { @@ -33,35 +45,33 @@ class EntitlementPoolsListEditorView extends React.Component { }; render() { - let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props; + let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode, version} = 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})} + title={i18n('Entitlement Pools', {vendorName})} plusButtonTitle={i18n('Add Entitlement Pool')} onAdd={onAddEntitlementPoolClick} filterValue={localFilter} - onFilter={filter => this.setState({localFilter: filter})} + onFilter={value => this.setState({localFilter: value})} isReadOnlyMode={isReadOnlyMode}> {this.filterList().map(entitlementPool => this.renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode))} </ListEditorView> - <Modal show={isDisplayModal} bsSize='large' animation={true} className='entitlement-pools-modal'> + <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal 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}/> + <EntitlementPoolsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/> ) } </Modal.Body> </Modal> - - <EntitlementPoolsConfirmationModal licenseModelId={licenseModelId}/> </div> ); } @@ -92,14 +102,15 @@ class EntitlementPoolsListEditorView extends React.Component { 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='textEllipses text name'>{name}</div></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 className='entitlement-parameters'>{`${extractValue(aggregationFunction)} ${extractValue(entitlementMetric)} per ${extractValue(time)}`}</div> + <div className='entitlement-pools-count'>{`${thresholdValue ? thresholdValue : ''} ${extractUnits(thresholdUnits)}`}</div> </div> <div className='list-editor-item-view-field'> @@ -115,18 +126,22 @@ class EntitlementPoolsListEditorView extends React.Component { ); } - - - 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; + +export function generateConfirmationMsg(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> + ); +} diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js index 63e351fce7..fefd823207 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListReducer.js @@ -1,23 +1,18 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {actionTypes} from './EntitlementPoolsConstants'; export default (state = [], action) => { switch (action.type) { diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js index c2b269bcf9..c6249c98ca 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js @@ -1,66 +1,78 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {connect} from 'react-redux'; import FeatureGroupsActionHelper from './FeatureGroupsActionHelper.js'; import FeatureGroupEditorView from './FeatureGroupEditorView.jsx'; +import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; -const mapStateToProps = ({licenseModel: {featureGroup, entitlementPool, licenseKeyGroup}}) => { - +export const mapStateToProps = ({licenseModel: {featureGroup, entitlementPool, licenseKeyGroup}}) => { + let {entitlementPoolsList = []} = entitlementPool; + let {licenseKeyGroupsList = []} = licenseKeyGroup; const {featureGroupEditor} = featureGroup; + let {data, selectedTab, genericFieldInfo, formReady} = featureGroupEditor; + const featureGroupId = data ? data.id : null; + const list = featureGroup.featureGroupsList; - let {data, selectedTab, selectedEntitlementPoolsButtonTab, selectedLicenseKeyGroupsButtonTab} = featureGroupEditor; + let previousData, FGNames = {}, isFormValid = true, invalidTabs = []; - let previousData; - const featureGroupId = data ? data.id : null; if (featureGroupId) { - previousData = featureGroup.featureGroupsList.find(featureGroup => featureGroup.id === featureGroupId); + previousData = list.find(featureGroup => featureGroup.id === featureGroupId); + } + + for (let i = 0; i < list.length; i++) { + FGNames[list[i].name] = list[i].id; + } + + for (let field in genericFieldInfo) { + if (!genericFieldInfo[field].isValid) { + isFormValid = false; + let tabId = genericFieldInfo[field].tabId; + if (invalidTabs.indexOf(tabId) === -1) { + invalidTabs[invalidTabs.length] = genericFieldInfo[field].tabId; + } + } } - let {entitlementPoolsList = []} = entitlementPool; - let {licenseKeyGroupsList = []} = licenseKeyGroup; return { data, previousData, selectedTab, - selectedEntitlementPoolsButtonTab, - selectedLicenseKeyGroupsButtonTab, entitlementPoolsList, - licenseKeyGroupsList + licenseKeyGroupsList, + isFormValid, + formReady, + genericFieldInfo, + invalidTabs, + FGNames }; }; -const mapActionsToProps = (dispatch, {licenseModelId}) => { +const mapActionsToProps = (dispatch, {licenseModelId, version}) => { return { + onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}), onTabSelect: tab => FeatureGroupsActionHelper.selectEntitlementPoolsEditorTab(dispatch, {tab}), - onEntitlementPoolsButtonTabSelect: buttonTab => FeatureGroupsActionHelper.selectFeatureGroupsEditorEntitlementPoolsButtonTab(dispatch, {buttonTab}), - onLicenseKeyGroupsButtonTabSelect: buttonTab => FeatureGroupsActionHelper.selectFeatureGroupsEditorLicenseKeyGroupsButtonTab(dispatch, {buttonTab}), - onDataChanged: deltaData => FeatureGroupsActionHelper.featureGroupsEditorDataChanged(dispatch, {deltaData}), onSubmit: (previousFeatureGroup, featureGroup) => { FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch); - FeatureGroupsActionHelper.saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup}); - } + FeatureGroupsActionHelper.saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup, version}); + }, + onCancel: () => FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch), + onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName) }; }; export default connect(mapStateToProps, mapActionsToProps)(FeatureGroupEditorView); - diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx index 6fecd16b71..5ae22cba95 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx @@ -1,27 +1,125 @@ +/*! + * 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. + */ import React from 'react'; -import ValidationTabs from 'nfvo-components/input/validation/ValidationTabs.jsx'; -import ValidationTab from 'nfvo-components/input/validation/ValidationTab.jsx'; -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 Tabs from 'nfvo-components/input/validation/Tabs.jsx'; +import Tab from 'react-bootstrap/lib/Tab.js'; +import GridSection from 'nfvo-components/grid/GridSection.jsx'; +import GridItem from 'nfvo-components/grid/GridItem.jsx'; +import Form from 'nfvo-components/input/validation/Form.jsx'; import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx'; -import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx'; -import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx'; -import ListEditorViewItem from 'nfvo-components/listEditor/ListEditorItemView.jsx'; +import Input from 'nfvo-components/input/validation/Input.jsx'; import i18n from 'nfvo-utils/i18n/i18n.js'; +import Validator from 'nfvo-utils/Validator.js'; -import {state as FeatureGroupStateConstants} from './FeatureGroupsConstants.js'; +import {state as FeatureGroupStateConstants, FG_EDITOR_FORM} from './FeatureGroupsConstants.js'; const FeatureGroupsPropType = React.PropTypes.shape({ id: React.PropTypes.string, name: React.PropTypes.string, description: React.PropTypes.string, partNumber: React.PropTypes.string, - entitlementPoolsIds: React.PropTypes.array(React.PropTypes.string), - licenseKeyGroupsIds: React.PropTypes.array(React.PropTypes.string) + entitlementPoolsIds: React.PropTypes.arrayOf(React.PropTypes.string), + licenseKeyGroupsIds: React.PropTypes.arrayOf(React.PropTypes.string) }); +const GeneralTab = ({data = {}, onDataChanged, genericFieldInfo, validateName}) => { + let {name, description, partNumber} = data; + return ( + <GridSection> + <GridItem colSpan={2}> + <Input + groupClassName='field-section' + onChange={name => onDataChanged({name}, FG_EDITOR_FORM, {name: validateName})} + label={i18n('Name')} + data-test-id='create-fg-name' + value={name} + name='feature-group-name' + type='text' + isRequired={true} + isValid={genericFieldInfo.name.isValid} + errorText={genericFieldInfo.name.errorText} /> + <Input + groupClassName='field-section' + className='description-field' + onChange={description => onDataChanged({description}, FG_EDITOR_FORM)} + data-test-id='create-fg-description' + label={i18n('Description')} + value={description} + name='feature-group-description' + type='textarea' + isRequired={true} + isValid={genericFieldInfo.description.isValid} + errorText={genericFieldInfo.description.errorText} /> + <Input + groupClassName='field-section' + onChange={partNumber => onDataChanged({partNumber}, FG_EDITOR_FORM)} + label={i18n('Part Number')} + data-test-id='create-fg-part-number' + value={partNumber} + isRequired={true} + type='text' + isValid={genericFieldInfo.partNumber.isValid} + errorText={genericFieldInfo.partNumber.errorText} /> + </GridItem> + </GridSection> + ); +}; + +const EntitlementPoolsTab = ({entitlementPoolsList, data, onDataChanged, isReadOnlyMode}) => { + const dualBoxFilterTitle = { + left: i18n('Available Entitlement Pools'), + right: i18n('Selected Entitlement Pools') + }; + if (entitlementPoolsList.length > 0) { + return ( + <DualListboxView + isReadOnlyMode={isReadOnlyMode} + filterTitle={dualBoxFilterTitle} + selectedValuesList={data.entitlementPoolsIds} + availableList={entitlementPoolsList} + onChange={ selectedValuesList => onDataChanged( { entitlementPoolsIds: selectedValuesList }, FG_EDITOR_FORM )}/> + ); + } else { + return ( + <p>{i18n('There is no available entitlement pools')}</p> + ); + } +}; + +const LKGTab = ({licenseKeyGroupsList, data, onDataChanged, isReadOnlyMode}) => { + const dualBoxFilterTitle = { + left: i18n('Available License Key Groups'), + right: i18n('Selected License Key Groups') + }; + if (licenseKeyGroupsList.length > 0) { + return ( + <DualListboxView + isReadOnlyMode={isReadOnlyMode} + filterTitle={dualBoxFilterTitle} + selectedValuesList={data.licenseKeyGroupsIds} + availableList={licenseKeyGroupsList} + onChange={ selectedValuesList => onDataChanged( { licenseKeyGroupsIds: selectedValuesList }, FG_EDITOR_FORM )}/> + ); + } else { + return ( + <p>{i18n('There is no available licsense key groups')}</p> + ); + } +}; + class FeatureGroupEditorView extends React.Component { @@ -29,6 +127,7 @@ class FeatureGroupEditorView extends React.Component { data: FeatureGroupsPropType, previousData: FeatureGroupsPropType, isReadOnlyMode: React.PropTypes.bool, + FGNames: React.PropTypes.object, onSubmit: React.PropTypes.func, onCancel: React.PropTypes.func, @@ -36,11 +135,6 @@ class FeatureGroupEditorView extends React.Component { selectedTab: React.PropTypes.number, onTabSelect: React.PropTypes.func, - selectedEntitlementPoolsButtonTab: React.PropTypes.number, - selectedLicenseKeyGroupsButtonTab: React.PropTypes.number, - onEntitlementPoolsButtonTabSelect: React.PropTypes.func, - onLicenseKeyGroupsButtonTabSelect: React.PropTypes.func, - entitlementPoolsList: DualListboxView.propTypes.availableList, licenseKeyGroupsList: DualListboxView.propTypes.availableList }; @@ -49,8 +143,6 @@ class FeatureGroupEditorView extends React.Component { static defaultProps = { data: {}, selectedTab: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL, - selectedEntitlementPoolsButtonTab: FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.ASSOCIATED_ENTITLEMENT_POOLS, - selectedLicenseKeyGroupsButtonTab: FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.ASSOCIATED_LICENSE_KEY_GROUPS }; state = { @@ -60,24 +152,39 @@ class FeatureGroupEditorView extends React.Component { render() { - let {selectedTab, onTabSelect, isReadOnlyMode} = this.props; + let {selectedTab, onTabSelect, isReadOnlyMode, invalidTabs, data, onDataChanged, genericFieldInfo, entitlementPoolsList, licenseKeyGroupsList} = this.props; return ( - <ValidationForm + <div> + { genericFieldInfo && <Form ref='validationForm' hasButtons={true} onSubmit={ () => this.submit() } + isValid={this.props.isFormValid} + formReady={this.props.formReady} + onValidateForm={() => this.props.onValidateForm(FG_EDITOR_FORM) } onReset={ () => this.props.onCancel() } labledButtons={true} isReadOnlyMode={isReadOnlyMode} name='feature-group-validation-form' className='feature-group-form'> - <ValidationTabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect}> - {this.renderGeneralTab()} - {this.renderEntitlementPoolsTab()} - {this.renderLicenseKeyGroupsTab()} - </ValidationTabs> - - </ValidationForm> + <Tabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect} invalidTabs={invalidTabs} id='vlmFGValTabs' > + <Tab eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL} title={i18n('General')} > + <GeneralTab data={data} onDataChanged={onDataChanged} genericFieldInfo={genericFieldInfo} validateName={(value)=> this.validateName(value)}/> + </Tab> + <Tab + eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS} + title={i18n('Entitlement Pools')} > + <EntitlementPoolsTab isReadOnlyMode={isReadOnlyMode} data={data} onDataChanged={onDataChanged} entitlementPoolsList={entitlementPoolsList} /> + </Tab> + <Tab + eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENSE_KEY_GROUPS} + title={i18n('License Key Groups')} > + <LKGTab isReadOnlyMode={isReadOnlyMode} data={data} onDataChanged={onDataChanged} licenseKeyGroupsList={licenseKeyGroupsList} /> + </Tab> + </Tabs> + + </Form> } + </div> ); } @@ -86,254 +193,14 @@ class FeatureGroupEditorView extends React.Component { this.props.onSubmit(previousFeatureGroup, featureGroup); } - renderGeneralTab() { - let {data = {}, onDataChanged} = this.props; - let {name, description, partNumber} = data; - return ( - <ValidationTab eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL} title={i18n('General')}> - <div> - <ValidationInput - groupClassName='field-section' - onChange={name => onDataChanged({name})} - ref='name' - label={i18n('Name')} - value={name} - name='feature-group-name' - validations={{maxLength: 120, required: true}} - type='text'/> - <ValidationInput - groupClassName='field-section' - className='description-field' - onChange={description => onDataChanged({description})} - ref='description' - label={i18n('Description')} - value={description} - name='feature-group-description' - validations={{maxLength: 1000, required: true}} - type='textarea'/> - <ValidationInput - groupClassName='field-section' - onChange={partNumber => onDataChanged({partNumber})} - label={i18n('Part Number')} - value={partNumber} - validations={{required: true}} - type='text'/> - </div> - </ValidationTab> - ); - } - - renderEntitlementPoolsTab() { - let {selectedEntitlementPoolsButtonTab, onEntitlementPoolsButtonTabSelect, entitlementPoolsList} = this.props; - if (entitlementPoolsList.length > 0) { - return ( - <ValidationTab - eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS} - title={i18n('Entitlement Pools')}> - <ButtonGroup> - { - this.renderButtonsTab( - FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.ASSOCIATED_ENTITLEMENT_POOLS, - selectedEntitlementPoolsButtonTab, - i18n('Associated Entitlement Pools'), - onEntitlementPoolsButtonTabSelect - ) - } - { - this.renderButtonsTab( - FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.AVAILABLE_ENTITLEMENT_POOLS, - selectedEntitlementPoolsButtonTab, - i18n('Available Entitlement Pools'), - onEntitlementPoolsButtonTabSelect - ) - } - </ButtonGroup> - {this.renderEntitlementPoolsButtonTabContent(selectedEntitlementPoolsButtonTab)} - </ValidationTab> - ); - } else { - return ( - <ValidationTab - eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS} - title={i18n('Entitlement Pools')}> - <p>{i18n('There is no available entitlement pools.')}</p> - </ValidationTab> - ); - } - } - - renderLicenseKeyGroupsTab() { - let {selectedLicenseKeyGroupsButtonTab, onLicenseKeyGroupsButtonTabSelect, licenseKeyGroupsList} = this.props; - if (licenseKeyGroupsList.length > 0) { - return ( - <ValidationTab - eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS} - title={i18n('License Key Groups')}> - <ButtonGroup> - { - this.renderButtonsTab( - FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.ASSOCIATED_LICENSE_KEY_GROUPS, - selectedLicenseKeyGroupsButtonTab, - i18n('Associated License Key Groups'), - onLicenseKeyGroupsButtonTabSelect - ) - } - { - this.renderButtonsTab( - FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.AVAILABLE_LICENSE_KEY_GROUPS, - selectedLicenseKeyGroupsButtonTab, - i18n('Available License Key Groups'), - onLicenseKeyGroupsButtonTabSelect - ) - } - </ButtonGroup> - {this.renderLicenseKeyGroupsTabContent(selectedLicenseKeyGroupsButtonTab)} - </ValidationTab> - ); - } else { - return ( - <ValidationTab - eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS} - title={i18n('License Key Groups')}> - <p>{i18n('There is no available license key groups')}</p> - </ValidationTab>); - } - } - - renderButtonsTab(buttonTab, selectedButtonTab, title, onClick) { - const isSelected = buttonTab === selectedButtonTab; - return ( - <Button - className='button-tab' - active={isSelected} - onClick={() => !isSelected && onClick(buttonTab)}> - { title } - </Button> - ); - } - - renderEntitlementPoolsButtonTabContent(selectedFeatureGroupsButtonTab) { - const {entitlementPoolsList = [], data: {entitlementPoolsIds = []}} = this.props; - let dualBoxTitle = { - left: i18n('Available Entitlement Pools'), - right: i18n('Selected Entitlement Pools') - }; - - if (entitlementPoolsList.length) { - const {localEntitlementPoolsListFilter} = this.state; - let selectedEntitlementPools = entitlementPoolsIds.map(entitlementPoolId => entitlementPoolsList.find(entitlementPool => entitlementPool.id === entitlementPoolId)); - - switch (selectedFeatureGroupsButtonTab) { - case FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.ASSOCIATED_ENTITLEMENT_POOLS: - if (selectedEntitlementPools.length) { - return ( - <ListEditorView - className='thinner-list' - filterValue={localEntitlementPoolsListFilter} - onFilter={localEntitlementPoolsListFilter => this.setState({localEntitlementPoolsListFilter})}> - {this.filterAssociatedItems(selectedEntitlementPools, localEntitlementPoolsListFilter) - .map(entitlementPool => this.renderAssociatedListItem(entitlementPool - , FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS))} - </ListEditorView> - ); - } - else { - return ( - <div> - <br/>{i18n('There are currently no entitlement pools associated with this feature group. Click "Available Entitlement Pools" to associate.')} - </div> - ); - } - case FeatureGroupStateConstants.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB.AVAILABLE_ENTITLEMENT_POOLS: - return ( - <DualListboxView - filterTitle={dualBoxTitle} - selectedValuesList={entitlementPoolsIds} - availableList={entitlementPoolsList} - onChange={ selectedValuesList => this.props.onDataChanged( { entitlementPoolsIds: selectedValuesList } )}/> - ); - } - } - } - - renderLicenseKeyGroupsTabContent(selectedFeatureGroupsButtonTab) { - const {licenseKeyGroupsList = [], data: {licenseKeyGroupsIds = []}} = this.props; - let dualBoxFilterTitle = { - left: i18n('Available License Key Groups'), - right: i18n('Selected License Key Groups') - }; - - if (licenseKeyGroupsList.length) { - const {localLicenseKeyGroupsListFilter} = this.state; - let selectedLicenseKeyGroups = licenseKeyGroupsIds.map(licenseKeyGroupId => licenseKeyGroupsList.find(licenseKeyGroup => licenseKeyGroup.id === licenseKeyGroupId)); - - switch (selectedFeatureGroupsButtonTab) { - case FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.ASSOCIATED_LICENSE_KEY_GROUPS: - if (selectedLicenseKeyGroups.length) { - return ( - <ListEditorView - className='thinner-list' - filterValue={localLicenseKeyGroupsListFilter} - onFilter={localLicenseKeyGroupsListFilter => this.setState({localLicenseKeyGroupsListFilter})}> - {this.filterAssociatedItems(selectedLicenseKeyGroups, localLicenseKeyGroupsListFilter) - .map(licenseKeyGroup => this.renderAssociatedListItem(licenseKeyGroup - , FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS))} - </ListEditorView> - ); - } else { - return ( - <div className='no-items-msg'> - {i18n('There are currently no license key groups associated with this feature group. Click "Available License Key Groups" to associate.')} - </div> - ); - } - case FeatureGroupStateConstants.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB.AVAILABLE_LICENSE_KEY_GROUPS: - return ( - <DualListboxView - filterTitle={dualBoxFilterTitle} - selectedValuesList={this.props.data.licenseKeyGroupsIds} - availableList={this.props.licenseKeyGroupsList} - onChange={ selectedValuesList => this.props.onDataChanged( { licenseKeyGroupsIds: selectedValuesList } )}/> - ); - } - } - } - - - renderAssociatedListItem(listItem, itemType) { - let {isReadOnlyMode} = this.props; - return ( - <ListEditorViewItem - key={listItem.id} - onDelete={() => this.deleteAssociatedItem(listItem.id, itemType)} - isReadOnlyMode={isReadOnlyMode}> - <div className='name'>{listItem.name}</div> - <div className='description'>{listItem.description}</div> - </ListEditorViewItem> - ); - } - - filterAssociatedItems(list, localList) { - if (localList) { - const filter = new RegExp(escape(localList), 'i'); - return list.filter(({name = '', description = ''}) => name.match(filter) || description.match(filter)); - } - else { - return list; - } - } - - deleteAssociatedItem(id, type) { - const {data: {licenseKeyGroupsIds = [], entitlementPoolsIds = []}} = this.props; - if (type === FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENCE_KEY_GROUPS) { - this.props.onDataChanged({licenseKeyGroupsIds: licenseKeyGroupsIds.filter(listId => listId !== id)}); - } else { - this.props.onDataChanged({entitlementPoolsIds: entitlementPoolsIds.filter(listId => listId !== id)}); - } + validateName(value) { + const {data: {id}, FGNames} = this.props; + const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: FGNames}); + return !isExists ? {isValid: true, errorText: ''} : + {isValid: false, errorText: i18n('Feature group by the name \'' + value + '\' already exists. Feature group name must be unique')}; } } export default FeatureGroupEditorView; - diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js index 9ea5a31490..83473a30bb 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditor.js @@ -1,35 +1,33 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {connect} from 'react-redux'; + import FeatureGroupsActionHelper from './FeatureGroupsActionHelper.js'; -import FeatureGroupListEditorView from './FeatureGroupListEditorView.jsx'; +import FeatureGroupListEditorView, {generateConfirmationMsg} from './FeatureGroupListEditorView.jsx'; import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import {actionTypes as globalMoadlActions} from 'nfvo-components/modal/GlobalModalConstants.js'; -const mapStateToProps = ({licenseModel: {featureGroup, licenseModelEditor}}) => { +export const mapStateToProps = ({licenseModel: {featureGroup, licenseModelEditor}}) => { const {featureGroupEditor: {data}, featureGroupsList} = featureGroup; - let {vendorName} = licenseModelEditor.data; + let {vendorName, version} = licenseModelEditor.data; let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data); - return { vendorName, + version, featureGroupsModal: { show: Boolean(data), editMode: Boolean(data && data.id) @@ -42,13 +40,19 @@ const mapStateToProps = ({licenseModel: {featureGroup, licenseModelEditor}}) => const mapActionsToProps = (dispatch, {licenseModelId}) => { return { - onDeleteFeatureGroupClick: (featureGroup) => FeatureGroupsActionHelper.openDeleteFeatureGroupConfirm(dispatch, {licenseModelId, featureGroup}), - onCancelFeatureGroupsEditor: () => FeatureGroupsActionHelper.closeFeatureGroupsEditor(dispatch), - - onAddFeatureGroupClick: () => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {licenseModelId}), - onEditFeatureGroupClick: featureGroup => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, { + onDeleteFeatureGroupClick: (featureGroup, version) => dispatch({ + type: globalMoadlActions.GLOBAL_MODAL_WARNING, + data:{ + msg: generateConfirmationMsg(featureGroup), + title: i18n('Warning'), + onConfirmed: ()=>FeatureGroupsActionHelper.deleteFeatureGroup(dispatch, {featureGroupId: featureGroup.id, licenseModelId, version}) + } + }), + onAddFeatureGroupClick: (actualVersion) => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {licenseModelId, version: actualVersion}), + onEditFeatureGroupClick: (featureGroup, actualVersion) => FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, { featureGroup, - licenseModelId + licenseModelId, + version: actualVersion }) }; }; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx index d998f9216f..bc0f5c71c0 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx @@ -1,3 +1,18 @@ +/*! + * 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. + */ import React from 'react'; import i18n from 'nfvo-utils/i18n/i18n.js'; @@ -6,7 +21,6 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx'; import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx'; import FeatureGroupEditor from './FeatureGroupEditor.js'; -import FeatureGroupsConfirmationModal from './FeatureGroupsConfirmationModal.jsx'; class FeatureGroupListEditorView extends React.Component { static propTypes = { @@ -37,46 +51,45 @@ class FeatureGroupListEditorView extends React.Component { }; render() { - let {vendorName, licenseModelId, featureGroupsModal, isReadOnlyMode, onAddFeatureGroupClick} = this.props; + let {vendorName, licenseModelId, featureGroupsModal, isReadOnlyMode, onAddFeatureGroupClick, version} = this.props; const {localFilter} = this.state; - return ( <div className='feature-groups-list-editor'> <ListEditorView - title={i18n('Feature Groups for {vendorName} License Model', {vendorName})} + title={i18n('Feature Groups', {vendorName})} plusButtonTitle={i18n('Add Feature Group')} filterValue={localFilter} - onFilter={filter => this.setState({localFilter: filter})} - onAdd={() => onAddFeatureGroupClick()} + onFilter={value => this.setState({localFilter: value})} + onAdd={() => onAddFeatureGroupClick(version)} isReadOnlyMode={isReadOnlyMode}> - {this.filterList().map(listItem => this.renderFeatureGroupListItem(listItem, isReadOnlyMode))} + {this.filterList().map(listItem => this.renderFeatureGroupListItem(listItem, isReadOnlyMode, version))} </ListEditorView> - <Modal show={featureGroupsModal.show} bsSize='large' animation={true} className='feature-group-modal'> - <Modal.Header> - <Modal.Title>{`${featureGroupsModal.editMode ? i18n('Edit Feature Group') : i18n('Create New Feature Group')}`}</Modal.Title> - </Modal.Header> - <Modal.Body> - <FeatureGroupEditor - onCancel={() => this.closeFeatureGroupsEditor()} - licenseModelId={licenseModelId} - isReadOnlyMode={isReadOnlyMode}/> - </Modal.Body> - </Modal> - - <FeatureGroupsConfirmationModal licenseModelId={licenseModelId}/> + {featureGroupsModal.show && <Modal show={featureGroupsModal.show} bsSize='large' animation={true} + className='onborading-modal feature-group-modal'> + <Modal.Header> + <Modal.Title>{`${featureGroupsModal.editMode ? i18n('Edit Feature Group') : i18n('Create New Feature Group')}`}</Modal.Title> + </Modal.Header> + <Modal.Body> + <FeatureGroupEditor + version={version} + licenseModelId={licenseModelId} + isReadOnlyMode={isReadOnlyMode}/> + </Modal.Body> + </Modal> + } </div> ); } - renderFeatureGroupListItem(listItem, isReadOnlyMode) { + renderFeatureGroupListItem(listItem, isReadOnlyMode, version) { let {name, description, entitlementPoolsIds = [], licenseKeyGroupsIds = []} = listItem; return ( <ListEditorItemView key={listItem.id} - onDelete={() => this.deleteFeatureGroupItem(listItem)} - onSelect={() => this.editFeatureGroupItem(listItem)} + onDelete={() => this.deleteFeatureGroupItem(listItem, version)} + onSelect={() => this.editFeatureGroupItem(listItem, version)} className='list-editor-item-view' isReadOnlyMode={isReadOnlyMode}> <div className='list-editor-item-view-field'> @@ -120,17 +133,28 @@ class FeatureGroupListEditorView extends React.Component { } } - closeFeatureGroupsEditor() { - this.props.onCancelFeatureGroupsEditor(); - } - - editFeatureGroupItem(featureGroup) { - this.props.onEditFeatureGroupClick(featureGroup); + editFeatureGroupItem(featureGroup, version) { + this.props.onEditFeatureGroupClick(featureGroup, version); } - deleteFeatureGroupItem(featureGroup) { - this.props.onDeleteFeatureGroupClick(featureGroup); + deleteFeatureGroupItem(featureGroup, version) { + this.props.onDeleteFeatureGroupClick(featureGroup, version); } } export default FeatureGroupListEditorView; + +export function generateConfirmationMsg(featureGroupToDelete) { + let name = featureGroupToDelete ? featureGroupToDelete.name : ''; + let msg = i18n('Are you sure you want to delete "{name}"?', {name}); + let subMsg = featureGroupToDelete.referencingLicenseAgreements + && featureGroupToDelete.referencingLicenseAgreements.length > 0 ? + i18n('This feature group is associated with one ore more license agreements') : + ''; + return ( + <div> + <p>{msg}</p> + <p>{subMsg}</p> + </div> + ); +} diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js index 3776c01263..a2015787a6 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js @@ -1,23 +1,18 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; import {actionTypes as featureGroupsActionConstants} from './FeatureGroupsConstants.js'; @@ -25,22 +20,22 @@ import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseMod import EntitlementPoolsActionHelper from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js'; import LicenseKeyGroupsActionHelper from 'sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js'; -function baseUrl(licenseModelId) { +function baseUrl(licenseModelId, version) { const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/feature-groups`; + const {id: versionId} = version; + return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/feature-groups`; } function fetchFeatureGroupsList(licenseModelId, version) { - let versionQuery = version ? `?version=${version}` : ''; - return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`); + return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`); } -function deleteFeatureGroup(licenseModelId, featureGroupId) { - return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${featureGroupId}`); +function deleteFeatureGroup(licenseModelId, featureGroupId, version) { + return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${featureGroupId}`); } -function addFeatureGroup(licenseModelId, featureGroup) { - return RestAPIUtil.create(baseUrl(licenseModelId), { +function addFeatureGroup(licenseModelId, featureGroup, version) { + return RestAPIUtil.post(baseUrl(licenseModelId, version), { name: featureGroup.name, description: featureGroup.description, partNumber: featureGroup.partNumber, @@ -49,13 +44,13 @@ function addFeatureGroup(licenseModelId, featureGroup) { }); } -function updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup) { +function updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup, version) { const {licenseKeyGroupsIds = []} = featureGroup; const {licenseKeyGroupsIds: prevLicenseKeyGroupsIds = []} = previousFeatureGroup; const {entitlementPoolsIds = []} = featureGroup; const {entitlementPoolsIds: prevEntitlementPoolsIds = []} = previousFeatureGroup; - return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${featureGroup.id}`, { + return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${featureGroup.id}`, { name: featureGroup.name, description: featureGroup.description, partNumber: featureGroup.partNumber, @@ -75,28 +70,37 @@ export default { })); }, - deleteFeatureGroup(dispatch, {licenseModelId, featureGroupId}) { - return deleteFeatureGroup(licenseModelId, featureGroupId).then(() => dispatch({ + deleteFeatureGroup(dispatch, {licenseModelId, featureGroupId, version}) { + return deleteFeatureGroup(licenseModelId, featureGroupId, version).then(() => dispatch({ type: featureGroupsActionConstants.DELETE_FEATURE_GROUPS, featureGroupId })); }, - saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup}) { + saveFeatureGroup(dispatch, {licenseModelId, previousFeatureGroup, featureGroup, version}) { if (previousFeatureGroup) { - return updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup).then(() => dispatch({ - type: featureGroupsActionConstants.EDIT_FEATURE_GROUPS, - featureGroup - })); + return updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup, version).then(() =>{ + dispatch({ + type: featureGroupsActionConstants.EDIT_FEATURE_GROUPS, + featureGroup + }); + EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version}); + LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version}); + }); } else { - return addFeatureGroup(licenseModelId, featureGroup).then(response => dispatch({ - type: featureGroupsActionConstants.ADD_FEATURE_GROUPS, - featureGroup: { - ...featureGroup, - id: response.value - } - })); + return addFeatureGroup(licenseModelId, featureGroup, version).then(response => { + dispatch({ + type: featureGroupsActionConstants.ADD_FEATURE_GROUPS, + featureGroup: { + ...featureGroup, + id: response.value, + referencingLicenseAgreements: [] + } + }); + EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version}); + LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version}); + }); } }, @@ -107,23 +111,9 @@ export default { }); }, - selectFeatureGroupsEditorEntitlementPoolsButtonTab(dispatch, {buttonTab}) { - dispatch({ - type: featureGroupsActionConstants.featureGroupsEditor.SELECTED_ENTITLEMENT_POOLS_BUTTONTAB, - buttonTab - }); - }, - - selectFeatureGroupsEditorLicenseKeyGroupsButtonTab(dispatch, {buttonTab}) { - dispatch({ - type: featureGroupsActionConstants.featureGroupsEditor.SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB, - buttonTab - }); - }, - - openFeatureGroupsEditor(dispatch, {featureGroup, licenseModelId}) { - EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId}); - LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId}); + openFeatureGroupsEditor(dispatch, {featureGroup, licenseModelId, version}) { + EntitlementPoolsActionHelper.fetchEntitlementPoolsList(dispatch, {licenseModelId, version}); + LicenseKeyGroupsActionHelper.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version}); dispatch({ type: featureGroupsActionConstants.featureGroupsEditor.OPEN, featureGroup @@ -136,26 +126,6 @@ export default { }); }, - featureGroupsEditorDataChanged(dispatch, {deltaData}) { - dispatch({ - type: featureGroupsActionConstants.featureGroupsEditor.DATA_CHANGED, - deltaData - }); - }, - - hideDeleteConfirm(dispatch) { - dispatch({ - type: featureGroupsActionConstants.FEATURE_GROUPS_DELETE_CONFIRM, - featureGroupToDelete: false - }); - }, - - openDeleteFeatureGroupConfirm(dispatch, {featureGroup}) { - dispatch({ - type: featureGroupsActionConstants.FEATURE_GROUPS_DELETE_CONFIRM, - featureGroupToDelete: featureGroup - }); - }, switchVersion(dispatch, {licenseModelId, version}) { LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => { diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConfirmationModal.jsx deleted file mode 100644 index 142ec3c4c8..0000000000 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConfirmationModal.jsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from 'react'; -import {connect} from 'react-redux'; -import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx'; -import FeatureGroupsActionHelper from './FeatureGroupsActionHelper.js'; -import i18n from 'nfvo-utils/i18n/i18n.js'; - -function renderMsg(featureGroupToDelete) { - let name = featureGroupToDelete ? featureGroupToDelete.name : ''; - let msg = i18n('Are you sure you want to delete "{name}"?', {name}); - let subMsg = featureGroupToDelete - && featureGroupToDelete.referencingLicenseAgreements - && featureGroupToDelete.referencingLicenseAgreements.length > 0 ? - i18n('This feature group is associated with one ore more license agreements') : - ''; - return ( - <div> - <p>{msg}</p> - <p>{subMsg}</p> - </div> - ); -}; - -const mapStateToProps = ({licenseModel: {featureGroup}}, {licenseModelId}) => { - let {featureGroupToDelete} = featureGroup; - const show = featureGroupToDelete !== false; - return { - show, - title: 'Warning!', - type: 'warning', - msg: renderMsg(featureGroupToDelete), - confirmationDetails: {featureGroupToDelete, licenseModelId} - }; -}; - -const mapActionsToProps = (dispatch) => { - return { - onConfirmed: ({featureGroupToDelete, licenseModelId}) => { - FeatureGroupsActionHelper.deleteFeatureGroup(dispatch, {featureGroupId: featureGroupToDelete.id, licenseModelId}); - FeatureGroupsActionHelper.hideDeleteConfirm(dispatch); - }, - onDeclined: () => { - FeatureGroupsActionHelper.hideDeleteConfirm(dispatch); - } - }; -}; - -export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView); - diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js index e02c54595d..4c5a94f239 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsConstants.js @@ -1,23 +1,18 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import keyMirror from 'nfvo-utils/KeyMirror.js'; export const actionTypes = keyMirror({ @@ -25,8 +20,6 @@ export const actionTypes = keyMirror({ ADD_FEATURE_GROUPS: null, EDIT_FEATURE_GROUPS: null, DELETE_FEATURE_GROUPS: null, - FEATURE_GROUPS_DELETE_CONFIRM: null, - ENTITLEMENT_POOLS_LIST_LOADED: null, @@ -34,27 +27,16 @@ export const actionTypes = keyMirror({ OPEN: null, CLOSE: null, DATA_CHANGED: null, - SELECT_TAB: null, - SELECTED_ENTITLEMENT_POOLS_BUTTONTAB: null, - SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB: null + SELECT_TAB: null } }); +export const FG_EDITOR_FORM = 'FG_EDITOR_FORM'; + export const state = 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 - }, - SELECTED_LICENSE_KEY_GROUPS_BUTTONTAB: { - ASSOCIATED_LICENSE_KEY_GROUPS: 1, - AVAILABLE_LICENSE_KEY_GROUPS: 2 - }, + LICENSE_KEY_GROUPS: 3 + } }); - - - diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js index 576a5358e6..001bd20d44 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js @@ -1,24 +1,20 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ -import {actionTypes} from './FeatureGroupsConstants.js'; +import {actionTypes, FG_EDITOR_FORM, state as FeatureGroupStateConstants} from './FeatureGroupsConstants.js'; @@ -27,14 +23,28 @@ export default (state = {}, action) => { case actionTypes.featureGroupsEditor.OPEN: return { ...state, - data: action.featureGroup || {} - }; - case actionTypes.featureGroupsEditor.DATA_CHANGED: - return { - ...state, - data: { - ...state.data, - ...action.deltaData + data: action.featureGroup || {}, + formReady: null, + formName: FG_EDITOR_FORM, + genericFieldInfo: { + 'description': { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}], + tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL + }, + 'partNumber': { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}], + tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL + }, + 'name': { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}], + tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL + } } }; case actionTypes.featureGroupsEditor.CLOSE: diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js index 5cf3248919..3b5f1c55e4 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsListReducer.js @@ -1,23 +1,18 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {actionTypes} from './FeatureGroupsConstants.js'; export default (state = [], action) => { switch (action.type) { diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js index 9616b60b76..efc4fb758f 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementActionHelper.js @@ -1,41 +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 - * + * + * 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========================================================= + * 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. */ - 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) { +function baseUrl(licenseModelId, version) { const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/license-agreements`; + const {id: versionId} = version; + return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/license-agreements`; } function fetchLicenseAgreementList(licenseModelId, version) { - let versionQuery = version ? `?version=${version}` : ''; - return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`); + return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`); } -function postLicenseAgreement(licenseModelId, licenseAgreement) { - return RestAPIUtil.create(baseUrl(licenseModelId), { +function postLicenseAgreement(licenseModelId, licenseAgreement, version) { + return RestAPIUtil.post(baseUrl(licenseModelId, version), { name: licenseAgreement.name, description: licenseAgreement.description, licenseTerm: licenseAgreement.licenseTerm, @@ -44,10 +39,10 @@ function postLicenseAgreement(licenseModelId, licenseAgreement) { }); } -function putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement) { +function putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement, version) { const {featureGroupsIds = []} = licenseAgreement; const {featureGroupsIds: prevFeatureGroupsIds = []} = previousLicenseAgreement; - return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${licenseAgreement.id}`, { + return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${licenseAgreement.id}`, { name: licenseAgreement.name, description: licenseAgreement.description, licenseTerm: licenseAgreement.licenseTerm, @@ -57,8 +52,8 @@ function putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAg }); } -function deleteLicenseAgreement(licenseModelId, licenseAgreementId) { - return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${licenseAgreementId}`); +function deleteLicenseAgreement(licenseModelId, licenseAgreementId, version) { + return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${licenseAgreementId}`); } export default { @@ -70,21 +65,14 @@ export default { })); }, - openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement}) { - FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId}); + openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement, version}) { + FeatureGroupsActionHelper.fetchFeatureGroupsList(dispatch, {licenseModelId, version}); dispatch({ type: licenseAgreementActionTypes.licenseAgreementEditor.OPEN, licenseAgreement }); }, - licenseAgreementEditorDataChanged(dispatch, {deltaData}) { - dispatch({ - type: licenseAgreementActionTypes.licenseAgreementEditor.DATA_CHANGED, - deltaData - }); - }, - closeLicenseAgreementEditor(dispatch) { dispatch({ type: licenseAgreementActionTypes.licenseAgreementEditor.CLOSE @@ -92,9 +80,9 @@ export default { }, - saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement}) { + saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement, version}) { if (previousLicenseAgreement) { - return putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement).then(() => { + return putLicenseAgreement(licenseModelId, previousLicenseAgreement, licenseAgreement, version).then(() => { dispatch({ type: licenseAgreementActionTypes.EDIT_LICENSE_AGREEMENT, licenseAgreement @@ -102,7 +90,7 @@ export default { }); } else { - return postLicenseAgreement(licenseModelId, licenseAgreement).then(response => { + return postLicenseAgreement(licenseModelId, licenseAgreement, version).then(response => { dispatch({ type: licenseAgreementActionTypes.ADD_LICENSE_AGREEMENT, licenseAgreement: { @@ -114,8 +102,8 @@ export default { } }, - deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId}) { - return deleteLicenseAgreement(licenseModelId, licenseAgreementId).then(() => { + deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId, version}) { + return deleteLicenseAgreement(licenseModelId, licenseAgreementId, version).then(() => { dispatch({ type: licenseAgreementActionTypes.DELETE_LICENSE_AGREEMENT, licenseAgreementId @@ -130,31 +118,9 @@ export default { }); }, - 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 deleted file mode 100644 index 42f2407696..0000000000 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConfirmationModal.jsx +++ /dev/null @@ -1,43 +0,0 @@ -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 index af5c454e22..998d5f0e8d 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js @@ -1,52 +1,43 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import keyMirror from 'nfvo-utils/KeyMirror.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; +import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx'; 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, + SELECT_TAB: null } }); +export const LA_EDITOR_FORM = 'LA_EDITOR_FORM'; + 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 } }); @@ -64,3 +55,11 @@ export const optionsInputValues = { {enum: 'Unlimited', title: 'Unlimited'} ] }; + +export const extractValue = (item) => { + if (item === undefined) { + return ''; + } //TODO fix it later + + return item ? item.choice === optionInputOther.OTHER ? item.other : InputOptions.getTitleByName(optionsInputValues, item.choice) : ''; +}; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js index 6a3e4dbc73..aada8ddca1 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js @@ -1,31 +1,29 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {connect} from 'react-redux'; import LicenseAgreementActionHelper from './LicenseAgreementActionHelper.js'; import LicenseAgreementEditorView from './LicenseAgreementEditorView.jsx'; +import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; export const mapStateToProps = ({licenseModel: {licenseAgreement, featureGroup}}) => { - let {data, selectedTab, selectedFeatureGroupsButtonTab} = licenseAgreement.licenseAgreementEditor; + let {data, selectedTab, genericFieldInfo, formReady} = licenseAgreement.licenseAgreementEditor; + const list = licenseAgreement.licenseAgreementList; + const LANames = {}; let previousData; const licenseAgreementId = data ? data.id : null; @@ -33,27 +31,47 @@ export const mapStateToProps = ({licenseModel: {licenseAgreement, featureGroup}} previousData = licenseAgreement.licenseAgreementList.find(licenseAgreement => licenseAgreement.id === licenseAgreementId); } + for (let i = 0; i < list.length; i++) { + LANames[list[i].name] = list[i].id; + } + const {featureGroupsList = []} = featureGroup; + let isFormValid = true; + let invalidTabs = []; + for (let field in genericFieldInfo) { + if (!genericFieldInfo[field].isValid) { + isFormValid = false; + let tabId = genericFieldInfo[field].tabId; + if (invalidTabs.indexOf(tabId) === -1) { + invalidTabs[invalidTabs.length] = genericFieldInfo[field].tabId; + } + } + } + return { data, previousData, selectedTab, - selectedFeatureGroupsButtonTab, - featureGroupsList + featureGroupsList, + LANames, + genericFieldInfo, + isFormValid, + formReady, + invalidTabs }; }; -export const mapActionsToProps = (dispatch, {licenseModelId}) => { +export const mapActionsToProps = (dispatch, {licenseModelId, version}) => { return { - onDataChanged: deltaData => LicenseAgreementActionHelper.licenseAgreementEditorDataChanged(dispatch, {deltaData}), + onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}), 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}); - } + LicenseAgreementActionHelper.saveLicenseAgreement(dispatch, {licenseModelId, previousLicenseAgreement, licenseAgreement, version}); + }, + onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName) }; }; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js index 74e2f6e8c1..e02935c579 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js @@ -1,40 +1,55 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - -import {actionTypes, defaultState} from './LicenseAgreementConstants.js'; +import {actionTypes, defaultState, LA_EDITOR_FORM, enums as LicenseAgreementEnums} from './LicenseAgreementConstants.js'; export default (state = {}, action) => { switch (action.type) { case actionTypes.licenseAgreementEditor.OPEN: return { ...state, + formReady: null, + formName: LA_EDITOR_FORM, + genericFieldInfo: { + 'description' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}], + tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL + }, + 'requirementsAndConstrains' : { + isValid: true, + errorText: '', + validations: [{type: 'maxLength', data: 1000}], + tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL + }, + 'licenseTerm' : { + isValid: true, + errorText: '', + validations: [], + tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL + }, + 'name' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 25}], + tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL + } + }, 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: @@ -42,11 +57,6 @@ export default (state = {}, action) => { ...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 index b21f943fed..67a3333a3a 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx @@ -1,17 +1,36 @@ +/*! + * 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. + */ 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 GridSection from 'nfvo-components/grid/GridSection.jsx'; +import GridItem from 'nfvo-components/grid/GridItem.jsx'; +import Form from 'nfvo-components/input/validation/Form.jsx'; +import Tabs from 'nfvo-components/input/validation/Tabs.jsx'; +import Tab from 'react-bootstrap/lib/Tab.js'; +import Input from 'nfvo-components/input/validation/Input.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 Validator from 'nfvo-utils/Validator.js'; -import {enums as LicenseAgreementEnums, optionsInputValues as LicenseAgreementOptionsInputValues} from './LicenseAgreementConstants.js'; +import {enums as LicenseAgreementEnums, optionsInputValues as LicenseAgreementOptionsInputValues, LA_EDITOR_FORM} from './LicenseAgreementConstants.js'; +const dualBoxFilterTitle = { + left: i18n('Available Feature Groups'), + right: i18n('Selected Feature Groups') +}; const LicenseAgreementPropType = React.PropTypes.shape({ id: React.PropTypes.string, @@ -19,14 +38,77 @@ const LicenseAgreementPropType = React.PropTypes.shape({ description: React.PropTypes.string, requirementsAndConstrains: React.PropTypes.string, licenseTerm: React.PropTypes.object, - featureGroupsIds: React.PropTypes.arrayOf(React.PropTypes.string) + featureGroupsIds: React.PropTypes.arrayOf(React.PropTypes.string), + version: React.PropTypes.object }); + +const GeneralTabContent = ({data, genericFieldInfo, onDataChanged, validateName, validateLTChoice}) => { + let {name, description, requirementsAndConstrains, licenseTerm} = data; + return ( + <GridSection> + <GridItem colSpan={2}> + <Input + isValid={genericFieldInfo.name.isValid} + errorText={genericFieldInfo.name.errorText} + onChange={name => onDataChanged({name}, LA_EDITOR_FORM, { name: validateName })} + label={i18n('Name')} + value={name} + data-test-id='create-la-name' + name='license-agreement-name' + isRequired={true} + type='text'/> + <Input + isValid={genericFieldInfo.requirementsAndConstrains.isValid} + errorText={genericFieldInfo.requirementsAndConstrains.errorText} + onChange={requirementsAndConstrains => onDataChanged({requirementsAndConstrains}, LA_EDITOR_FORM)} + label={i18n('Requirements and Constraints')} + value={requirementsAndConstrains} + data-test-id='create-la-requirements-constants' + name='license-agreement-requirements-and-constraints' + type='textarea'/> + <Input + label={i18n('License Term')} + type='select' + value={licenseTerm && licenseTerm.choice} + isRequired={true} + onChange={e => { + const selectedIndex = e.target.selectedIndex; + const licenseTerm = e.target.options[selectedIndex].value; + onDataChanged({licenseTerm:{choice: licenseTerm, other: ''}}, LA_EDITOR_FORM, { licenseTerm: validateLTChoice }); + }} + isValid={genericFieldInfo.licenseTerm.isValid} + errorText={genericFieldInfo.licenseTerm.errorText} + className='input-options-select' + groupClassName='bootstrap-input-options' + data-test-id='create-la-license-term' > + {LicenseAgreementOptionsInputValues.LICENSE_MODEL_TYPE.map(mtype => + <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)} + </Input> + </GridItem> + <GridItem colSpan={2} stretch> + <Input + isValid={genericFieldInfo.description.isValid} + errorText={genericFieldInfo.description.errorText} + onChange={description => onDataChanged({description}, LA_EDITOR_FORM)} + label={i18n('Description')} + value={description} + overlayPos='bottom' + data-test-id='create-la-description' + name='license-agreement-description' + isRequired={true} + type='textarea'/> + </GridItem> + </GridSection> + ); +}; + class LicenseAgreementEditorView extends React.Component { static propTypes = { data: LicenseAgreementPropType, previousData: LicenseAgreementPropType, + LANames: React.PropTypes.object, isReadOnlyMode: React.PropTypes.bool, onDataChanged: React.PropTypes.func.isRequired, onSubmit: React.PropTypes.func.isRequired, @@ -42,7 +124,6 @@ class LicenseAgreementEditorView extends React.Component { static defaultProps = { selectedTab: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL, - selectedFeatureGroupsButtonTab: LicenseAgreementEnums.SELECTED_FEATURE_GROUPS_BUTTONTAB.AVAILABLE_FEATURE_GROUPS, data: {} }; @@ -51,21 +132,44 @@ class LicenseAgreementEditorView extends React.Component { }; render() { - let {selectedTab, onTabSelect, isReadOnlyMode} = this.props; + let {selectedTab, onTabSelect, isReadOnlyMode, featureGroupsList, data, onDataChanged, genericFieldInfo} = 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> + <div> + {genericFieldInfo && <Form + ref='validationForm' + hasButtons={true} + onSubmit={ () => this.submit() } + onReset={ () => this.props.onCancel() } + labledButtons={true} + isReadOnlyMode={isReadOnlyMode} + isValid={this.props.isFormValid} + formReady={this.props.formReady} + onValidateForm={() => this.props.onValidateForm(LA_EDITOR_FORM) } + className='license-agreement-form'> + <Tabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect} invalidTabs={this.props.invalidTabs} > + <Tab + eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL} + data-test-id='general-tab' + title={i18n('General')}> + <GeneralTabContent data={data} genericFieldInfo={genericFieldInfo} onDataChanged={onDataChanged} validateLTChoice={(value)=>this.validateLTChoice(value)} + validateName={(value)=>this.validateName(value)}/> + </Tab> + <Tab + eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS} + data-test-id='feature-group-tab' + title={i18n('Feature Groups')}> + {featureGroupsList.length > 0 ? + <DualListboxView + isReadOnlyMode={isReadOnlyMode} + filterTitle={dualBoxFilterTitle} + selectedValuesList={data.featureGroupsIds} + availableList={featureGroupsList} + onChange={ selectedValuesList => onDataChanged( { featureGroupsIds: selectedValuesList }, LA_EDITOR_FORM )}/> : + <p>{i18n('There is no available feature groups')}</p>} + </Tab> + </Tabs> + </Form>} + </div> ); } @@ -74,173 +178,19 @@ class LicenseAgreementEditorView extends React.Component { 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> - ); + validateLTChoice(value) { + if (!value.choice) { + return {isValid: false, errorText: i18n('Field is required')}; } + return {isValid: true, errorText: ''}; } - 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 } )}/> - ); - } - } + validateName(value) { + const {data: {id}, LANames} = this.props; + const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: LANames}); - 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; - } + return !isExists ? {isValid: true, errorText: ''} : + {isValid: false, errorText: i18n('License Agreement by the name \'' + value + '\' already exists. License agreement name must be unique')}; } } diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js index ca18bfab79..373694f2bf 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditor.js @@ -1,39 +1,35 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {connect} from 'react-redux'; -import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js'; +import i18n from 'nfvo-utils/i18n/i18n.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'; +import {actionTypes as globalMoadlActions} from 'nfvo-components/modal/GlobalModalConstants.js'; const mapStateToProps = ({licenseModel: {licenseAgreement, licenseModelEditor}}) => { let {licenseAgreementList} = licenseAgreement; let {data} = licenseAgreement.licenseAgreementEditor; - let {vendorName} = licenseModelEditor.data; + let {vendorName, version} = licenseModelEditor.data; let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data); return { vendorName, + version, licenseAgreementList, isReadOnlyMode, isDisplayModal: Boolean(data), @@ -43,16 +39,16 @@ const mapStateToProps = ({licenseModel: {licenseAgreement, licenseModelEditor}}) 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) + onAddLicenseAgreementClick: (version) => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, version}), + onEditLicenseAgreementClick: (licenseAgreement, version) => LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, licenseAgreement, version}), + onDeleteLicenseAgreement: (licenseAgreement, version) => dispatch({ + type: globalMoadlActions.GLOBAL_MODAL_WARNING, + data:{ + msg: i18n('Are you sure you want to delete "{name}"?', {name: licenseAgreement.name}), + title: i18n('Warning'), + onConfirmed: ()=>LicenseAgreementActionHelper.deleteLicenseAgreement(dispatch, {licenseModelId, licenseAgreementId: licenseAgreement.id, version}) + } + }) }; }; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx index 4d7e704ba3..776b04b8eb 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx @@ -1,15 +1,26 @@ +/*! + * 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. + */ 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'; - +import {extractValue} from './LicenseAgreementConstants'; class LicenseAgreementListEditorView extends React.Component { static propTypes = { @@ -22,7 +33,6 @@ class LicenseAgreementListEditorView extends React.Component { onAddLicenseAgreementClick: React.PropTypes.func, onEditLicenseAgreementClick: React.PropTypes.func, onDeleteLicenseAgreement: React.PropTypes.func, - onCallVCAction: React.PropTypes.func }; static defaultProps = { @@ -34,35 +44,33 @@ class LicenseAgreementListEditorView extends React.Component { }; render() { - const {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props; + const {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode, version} = 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'> + <ListEditorView + title={i18n('License Agreements', {vendorName})} + plusButtonTitle={i18n('Add License Agreement')} + onAdd={() => onAddLicenseAgreementClick(version)} + filterValue={localFilter} + onFilter={value => this.setState({localFilter: value})} + isReadOnlyMode={isReadOnlyMode}> + {this.filterList().map(licenseAgreement => this.renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode, version))} + </ListEditorView> + <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal 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} /> + <LicenseAgreementEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode} /> ) } </Modal.Body> </Modal> - <LicenseAgreementConfirmationModal licenseModelId={licenseModelId}/> - </div> ); } @@ -73,7 +81,7 @@ class LicenseAgreementListEditorView extends React.Component { 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); + return escape(name).match(filter) || escape(description).match(filter) || escape(extractValue(licenseTerm)).match(filter); }); } else { @@ -81,14 +89,14 @@ class LicenseAgreementListEditorView extends React.Component { } } - renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode) { + renderLicenseAgreementListItem(licenseAgreement, isReadOnlyMode, version) { let {id, name, description, licenseTerm, featureGroupsIds = []} = licenseAgreement; let {onEditLicenseAgreementClick, onDeleteLicenseAgreement} = this.props; return ( <ListEditorItemView key={id} - onSelect={() => onEditLicenseAgreementClick(licenseAgreement)} - onDelete={() => onDeleteLicenseAgreement(licenseAgreement)} + onSelect={() => onEditLicenseAgreementClick(licenseAgreement, version)} + onDelete={() => onDeleteLicenseAgreement(licenseAgreement, version)} className='list-editor-item-view' isReadOnlyMode={isReadOnlyMode}> <div className='list-editor-item-view-field'> @@ -98,7 +106,7 @@ class LicenseAgreementListEditorView extends React.Component { <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 className='text type'>{extractValue(licenseTerm)}</div> </div> <div className='list-editor-item-view-field-tight'> <div className='title'>{i18n('Feature')}</div> @@ -113,14 +121,6 @@ class LicenseAgreementListEditorView extends React.Component { </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 index 5b5fa00df1..e6a8f34b58 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListReducer.js @@ -1,23 +1,18 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {actionTypes as licenseAgreementActionTypes} from './LicenseAgreementConstants'; export default (state = [], action) => { diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js index 50ac2c85a3..dd2a5c6003 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js @@ -1,44 +1,39 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js'; import Configuration from 'sdc-app/config/Configuration.js'; import {actionTypes as licenseKeyGroupsConstants} from './LicenseKeyGroupsConstants.js'; import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js'; -function baseUrl(licenseModelId) { +function baseUrl(licenseModelId, version) { const restPrefix = Configuration.get('restPrefix'); - return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/license-key-groups`; + const {id: versionId} = version; + return `${restPrefix}/v1.0/vendor-license-models/${licenseModelId}/versions/${versionId}/license-key-groups`; } function fetchLicenseKeyGroupsList(licenseModelId, version) { - let versionQuery = version ? `?version=${version}` : ''; - return RestAPIUtil.fetch(`${baseUrl(licenseModelId)}${versionQuery}`); + return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`); } -function deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId) { - return RestAPIUtil.destroy(`${baseUrl(licenseModelId)}/${licenseKeyGroupId}`); +function deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId, version) { + return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}`); } -function postLicenseKeyGroup(licenseModelId, licenseKeyGroup) { - return RestAPIUtil.create(baseUrl(licenseModelId), { +function postLicenseKeyGroup(licenseModelId, licenseKeyGroup, version) { + return RestAPIUtil.post(baseUrl(licenseModelId, version), { name: licenseKeyGroup.name, description: licenseKeyGroup.description, operationalScope: licenseKeyGroup.operationalScope, @@ -46,8 +41,8 @@ function postLicenseKeyGroup(licenseModelId, licenseKeyGroup) { }); } -function putLicenseKeyGroup(licenseModelId, licenseKeyGroup) { - return RestAPIUtil.save(`${baseUrl(licenseModelId)}/${licenseKeyGroup.id}`, { +function putLicenseKeyGroup(licenseModelId, licenseKeyGroup, version) { + return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${licenseKeyGroup.id}`, { name: licenseKeyGroup.name, description: licenseKeyGroup.description, operationalScope: licenseKeyGroup.operationalScope, @@ -77,9 +72,9 @@ export default { }); }, - saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup}) { + saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup, version}) { if (previousLicenseKeyGroup) { - return putLicenseKeyGroup(licenseModelId, licenseKeyGroup).then(() => { + return putLicenseKeyGroup(licenseModelId, licenseKeyGroup, version).then(() => { dispatch({ type: licenseKeyGroupsConstants.EDIT_LICENSE_KEY_GROUP, licenseKeyGroup @@ -87,11 +82,12 @@ export default { }); } else { - return postLicenseKeyGroup(licenseModelId, licenseKeyGroup).then(response => { + return postLicenseKeyGroup(licenseModelId, licenseKeyGroup, version).then(response => { dispatch({ type: licenseKeyGroupsConstants.ADD_LICENSE_KEY_GROUP, licenseKeyGroup: { ...licenseKeyGroup, + referencingFeatureGroups: [], id: response.value } }); @@ -101,8 +97,8 @@ export default { }, - deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId}){ - return deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId).then(()=> { + deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId, version}){ + return deleteLicenseKeyGroup(licenseModelId, licenseKeyGroupId, version).then(()=> { dispatch({ type: licenseKeyGroupsConstants.DELETE_LICENSE_KEY_GROUP, licenseKeyGroupId @@ -110,13 +106,6 @@ export default { }); }, - licenseKeyGroupEditorDataChanged(dispatch, {deltaData}) { - dispatch({ - type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.DATA_CHANGED, - deltaData - }); - }, - hideDeleteConfirm(dispatch) { dispatch({ type: licenseKeyGroupsConstants.LICENSE_KEY_GROUPS_DELETE_CONFIRM, diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConfirmationModal.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConfirmationModal.jsx deleted file mode 100644 index 2413db51d0..0000000000 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConfirmationModal.jsx +++ /dev/null @@ -1,49 +0,0 @@ -import React from 'react'; -import {connect} from 'react-redux'; -import ConfirmationModalView from 'nfvo-components/confirmations/ConfirmationModalView.jsx'; -import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js'; -import i18n from 'nfvo-utils/i18n/i18n.js'; - -function renderMsg(licenseKeyGroupToDelete) { - let name = licenseKeyGroupToDelete ? licenseKeyGroupToDelete.name : ''; - let msg = i18n('Are you sure you want to delete "{name}"?', {name}); - let subMsg = licenseKeyGroupToDelete - && licenseKeyGroupToDelete.referencingFeatureGroups - && licenseKeyGroupToDelete.referencingFeatureGroups.length > 0 ? - i18n('This license key group is associated with one or more feature groups') : - ''; - return( - <div> - <p>{msg}</p> - <p>{subMsg}</p> - </div> - ); -}; - -const mapStateToProps = ({licenseModel: {licenseKeyGroup}}, {licenseModelId}) => { - let {licenseKeyGroupToDelete} = licenseKeyGroup; - const show = licenseKeyGroupToDelete !== false; - return { - show, - title: 'Warning!', - type: 'warning', - msg: renderMsg(licenseKeyGroupToDelete), - confirmationDetails: {licenseKeyGroupToDelete, licenseModelId} - }; -}; - -const mapActionsToProps = (dispatch) => { - return { - onConfirmed: ({licenseKeyGroupToDelete, licenseModelId}) => { - - LicenseKeyGroupsActionHelper.deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId:licenseKeyGroupToDelete.id}); - LicenseKeyGroupsActionHelper.hideDeleteConfirm(dispatch); - }, - onDeclined: () => { - LicenseKeyGroupsActionHelper.hideDeleteConfirm(dispatch); - } - }; -}; - -export default connect(mapStateToProps, mapActionsToProps)(ConfirmationModalView); - diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js index d32bc52744..50d1fe8625 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js @@ -1,25 +1,21 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import keyMirror from 'nfvo-utils/KeyMirror.js'; import i18n from 'nfvo-utils/i18n/i18n.js'; +import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx'; export const actionTypes = keyMirror({ @@ -42,6 +38,8 @@ export const defaultState = { } }; +export const LKG_FORM_NAME = 'LKGFORM'; + export const optionsInputValues = { OPERATIONAL_SCOPE: [ {enum: '', title: i18n('please select…')}, @@ -61,4 +59,21 @@ export const optionsInputValues = { ] }; +export const extractValue = (item) => { + if (item === undefined) {return '';} //TODO fix it later + + return item ? item === optionInputOther.OTHER ? item : InputOptions.getTitleByName(optionsInputValues, item) : ''; +}; +export const getOperationalScopes = (operationalScope) => { + if(operationalScope.choices.toString() === i18n(optionInputOther.OTHER) && operationalScope.other !== '') { + return operationalScope.other; + } + else { + let allOpScopes = ''; + for (let opScope of operationalScope.choices) { + allOpScopes += allOpScopes === '' ? InputOptions.getTitleByName(optionsInputValues, opScope) : `, ${InputOptions.getTitleByName(optionsInputValues, opScope)}`; + } + return allOpScopes; + } +}; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js index 3940ec594a..aef1532dc1 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js @@ -1,52 +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 - * + * + * 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========================================================= + * 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. */ - import {connect} from 'react-redux'; import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js'; import LicenseKeyGroupsEditorView from './LicenseKeyGroupsEditorView.jsx'; +import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; const mapStateToProps = ({licenseModel: {licenseKeyGroup}}) => { - let {data} = licenseKeyGroup.licenseKeyGroupsEditor; + let {data, genericFieldInfo, formReady} = licenseKeyGroup.licenseKeyGroupsEditor; - let previousData; + let previousData, LKGNames = {}; const licenseKeyGroupId = data ? data.id : null; if(licenseKeyGroupId) { previousData = licenseKeyGroup.licenseKeyGroupsList.find(licenseKeyGroup => licenseKeyGroup.id === licenseKeyGroupId); } + let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo); + + const list = licenseKeyGroup.licenseKeyGroupsList; + for (let i = 0; i < list.length; i++) { + LKGNames[list[i].name] = list[i].id; + } + return { data, - previousData + previousData, + genericFieldInfo, + isFormValid, + formReady, + LKGNames }; }; -const mapActionsToProps = (dispatch, {licenseModelId}) => { +const mapActionsToProps = (dispatch, {licenseModelId, version}) => { return { - onDataChanged: deltaData => LicenseKeyGroupsActionHelper.licenseKeyGroupEditorDataChanged(dispatch, {deltaData}), + onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}), onCancel: () => LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch), onSubmit: ({previousLicenseKeyGroup, licenseKeyGroup}) => { LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch); - LicenseKeyGroupsActionHelper.saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup}); - } + LicenseKeyGroupsActionHelper.saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup, version}); + }, + onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName) }; }; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js index a74498269a..090c971c65 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js @@ -1,42 +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 - * + * + * 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========================================================= + * 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. */ - -import {actionTypes, defaultState} from './LicenseKeyGroupsConstants.js'; +import {actionTypes, defaultState, LKG_FORM_NAME} from './LicenseKeyGroupsConstants.js'; export default (state = {}, action) => { switch (action.type) { case actionTypes.licenseKeyGroupsEditor.OPEN: return { ...state, - data: action.licenseKeyGroup ? {...action.licenseKeyGroup} : defaultState.licenseKeyGroupsEditor + data: action.licenseKeyGroup ? {...action.licenseKeyGroup} : defaultState.licenseKeyGroupsEditor, + formReady: null, + formName: LKG_FORM_NAME, + genericFieldInfo: { + 'description' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}] + }, + 'name' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}] + }, + 'type' : { + isValid: true, + errorText: '', + validations: [{type: 'required', data: true}] + }, + 'operationalScope' : { + isValid: true, + errorText: '', + validations: [] + } + } }; case actionTypes.licenseKeyGroupsEditor.CLOSE: return {}; - case actionTypes.licenseKeyGroupsEditor.DATA_CHANGED: - return { - ...state, - data: { - ...state.data, - ...action.deltaData - } - }; default: return state; } diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx index 102e713060..b95efd0f9c 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx @@ -1,10 +1,29 @@ +/*! + * 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. + */ import React from 'react'; import i18n from 'nfvo-utils/i18n/i18n.js'; +import Validator from 'nfvo-utils/Validator.js'; -import ValidationForm from 'nfvo-components/input/validation/ValidationForm.jsx'; -import ValidationInput from 'nfvo-components/input/validation/ValidationInput.jsx'; -import {optionsInputValues as licenseKeyGroupOptionsInputValues} from './LicenseKeyGroupsConstants.js'; -import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx'; +import Form from 'nfvo-components/input/validation/Form.jsx'; +import Input from 'nfvo-components/input/validation/Input.jsx'; +import GridSection from 'nfvo-components/grid/GridSection.jsx'; +import GridItem from 'nfvo-components/grid/GridItem.jsx'; +import {optionsInputValues as licenseKeyGroupOptionsInputValues, LKG_FORM_NAME} from './LicenseKeyGroupsConstants.js'; +import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx'; +import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx'; const LicenseKeyGroupPropType = React.PropTypes.shape({ id: React.PropTypes.string, @@ -17,10 +36,80 @@ const LicenseKeyGroupPropType = React.PropTypes.shape({ type: React.PropTypes.string }); +const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, validateName, validateOperationalScope}) => { + let {name, description, operationalScope, type} = data; + return ( + <GridSection> + <GridItem colSpan={2}> + <Input + onChange={name => onDataChanged({name}, LKG_FORM_NAME, {name: validateName})} + label={i18n('Name')} + data-test-id='create-lkg-name' + value={name} + isValid={genericFieldInfo.name.isValid} + errorText={genericFieldInfo.name.errorText} + isRequired={true} + type='text'/> + </GridItem> + <GridItem colSpan={2}> + <InputOptions + onInputChange={()=>{}} + isMultiSelect={true} + isRequired={true} + onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}}, + LKG_FORM_NAME, {operationalScope: validateOperationalScope})} + onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER], + other: operationalScope}}, LKG_FORM_NAME, {operationalScope: validateOperationalScope})} + label={i18n('Operational Scope')} + data-test-id='create-lkg-operational-scope' + type='select' + multiSelectedEnum={operationalScope && operationalScope.choices} + otherValue={operationalScope && operationalScope.other} + values={licenseKeyGroupOptionsInputValues.OPERATIONAL_SCOPE} + isValid={genericFieldInfo.operationalScope.isValid} + errorText={genericFieldInfo.operationalScope.errorText} /> + </GridItem> + <GridItem colSpan={2}> + <Input + onChange={description => onDataChanged({description}, LKG_FORM_NAME)} + label={i18n('Description')} + data-test-id='create-lkg-description' + value={description} + isValid={genericFieldInfo.description.isValid} + errorText={genericFieldInfo.description.errorText} + isRequired={true} + type='textarea' + overlayPos='bottom' /> + </GridItem> + <GridItem colSpan={2}> + <Input + isRequired={true} + onChange={e => { const selectedIndex = e.target.selectedIndex; + const val = e.target.options[selectedIndex].value; + onDataChanged({type: val}, LKG_FORM_NAME);}} + value={type} + label={i18n('Type')} + data-test-id='create-lkg-type' + isValid={genericFieldInfo.type.isValid} + errorText={genericFieldInfo.type.errorText} + groupClassName='bootstrap-input-options' + className='input-options-select' + type='select' > + { + licenseKeyGroupOptionsInputValues.TYPE.map(type => + (<option key={type.enum} value={type.enum}>{type.title}</option>)) + } + </Input> + </GridItem> + </GridSection> + ); +}; + class LicenseKeyGroupsEditorView extends React.Component { static propTypes = { data: LicenseKeyGroupPropType, previousData: LicenseKeyGroupPropType, + LKGNames: React.PropTypes.object, isReadOnlyMode: React.PropTypes.bool, onDataChanged: React.PropTypes.func.isRequired, onSubmit: React.PropTypes.func.isRequired, @@ -32,54 +121,29 @@ class LicenseKeyGroupsEditorView extends React.Component { }; render() { - let {data = {}, onDataChanged, isReadOnlyMode} = this.props; - let {name, description, operationalScope, type} = data; + let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo} = this.props; return ( - <ValidationForm + <div> + { genericFieldInfo && + <Form ref='validationForm' hasButtons={true} onSubmit={ () => this.submit() } onReset={ () => this.props.onCancel() } + isValid={this.props.isFormValid} + formReady={this.props.formReady} + onValidateForm={() => this.props.onValidateForm(LKG_FORM_NAME) } labledButtons={true} isReadOnlyMode={isReadOnlyMode} className='license-key-groups-form'> - <div className='license-key-groups-form-row'> - <ValidationInput - onChange={name => onDataChanged({name})} - ref='name' - label={i18n('Name')} - value={name} - validations={{maxLength: 120, required: true}} - type='text'/> - <ValidationInput - isMultiSelect={true} - isRequired={true} - onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}})} - onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER], other: operationalScope}})} - label={i18n('Operational Scope')} - validations={{required: true}} - multiSelectedEnum={operationalScope && operationalScope.choices} - otherValue={operationalScope && operationalScope.other} - values={licenseKeyGroupOptionsInputValues.OPERATIONAL_SCOPE}/> - </div> - <div className='license-key-groups-form-row'> - <ValidationInput - onChange={description => onDataChanged({description})} - ref='description' - label={i18n('Description')} - value={description} - validations={{maxLength: 1000, required: true}} - type='textarea'/> - <ValidationInput - isRequired={true} - onEnumChange={type => onDataChanged({type})} - selectedEnum={type} - label={i18n('Type')} - type='select' - validations={{required: true}} - values={licenseKeyGroupOptionsInputValues.TYPE}/> - </div> - </ValidationForm> + <LicenseKeyGroupFormContent + data={data} + onDataChanged={onDataChanged} + genericFieldInfo={genericFieldInfo} + validateName={(value)=> this.validateName(value)} + validateOperationalScope={this.validateOperationalScope}/> + </Form>} + </div> ); } @@ -87,6 +151,37 @@ class LicenseKeyGroupsEditorView extends React.Component { const {data: licenseKeyGroup, previousData: previousLicenseKeyGroup} = this.props; this.props.onSubmit({licenseKeyGroup, previousLicenseKeyGroup}); } + + validateName(value) { + const {data: {id}, LKGNames} = this.props; + const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: LKGNames}); + + return !isExists ? {isValid: true, errorText: ''} : + {isValid: false, errorText: i18n('License key group by the name \'' + value + '\' already exists. License key group name must be unique')}; + } + + validateOperationalScope(value) { + if (value && value.choices && value.choices.length > 0) { + if (value.choices[0] !== optionInputOther.OTHER) + { + return { + isValid: true, + errorText: '' + }; + } else { + if ( value.other ) { + return { + isValid: true, + errorText: '' + }; + } + } + } + return { + isValid: false, + errorText: 'Field is required' + }; + } } export default LicenseKeyGroupsEditorView; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js index e1b610f973..e2c6c30e21 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js @@ -1,27 +1,24 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {connect} from 'react-redux'; +import i18n from 'nfvo-utils/i18n/i18n.js'; import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js'; -import LicenseKeyGroupsListEditorView from './LicenseKeyGroupsListEditorView.jsx'; +import LicenseKeyGroupsListEditorView, {generateConfirmationMsg} from './LicenseKeyGroupsListEditorView.jsx'; import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js'; +import {actionTypes as globalMoadlActions} from 'nfvo-components/modal/GlobalModalConstants.js'; const mapStateToProps = ({licenseModel: {licenseKeyGroup, licenseModelEditor}}) => { let {licenseKeyGroupsList} = licenseKeyGroup; @@ -38,11 +35,18 @@ const mapStateToProps = ({licenseModel: {licenseKeyGroup, licenseModelEditor}}) }; }; -const mapActionsToProps = (dispatch) => { +const mapActionsToProps = (dispatch, {licenseModelId, version}) => { return { onAddLicenseKeyGroupClick: () => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch), onEditLicenseKeyGroupClick: licenseKeyGroup => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch, {licenseKeyGroup}), - onDeleteLicenseKeyGroupClick: licenseKeyGroup => LicenseKeyGroupsActionHelper.openDeleteLicenseAgreementConfirm(dispatch, {licenseKeyGroup}) + onDeleteLicenseKeyGroupClick: licenseKeyGroup => dispatch({ + type: globalMoadlActions.GLOBAL_MODAL_WARNING, + data:{ + msg: generateConfirmationMsg(licenseKeyGroup), + title: i18n('Warning'), + onConfirmed: ()=>LicenseKeyGroupsActionHelper.deleteLicenseKeyGroup(dispatch, {licenseModelId, licenseKeyGroupId:licenseKeyGroup.id, version}) + } + }) }; }; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx index 1ed1d2093a..a303e46706 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx @@ -1,3 +1,18 @@ +/*! + * 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. + */ import React from 'react'; import i18n from 'nfvo-utils/i18n/i18n.js'; @@ -8,8 +23,6 @@ import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.js import LicenseKeyGroupsEditor from './LicenseKeyGroupsEditor.js'; import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx'; import {optionsInputValues} from './LicenseKeyGroupsConstants'; -import LicenseKeyGroupsConfirmationModal from './LicenseKeyGroupsConfirmationModal.jsx'; - class LicenseKeyGroupsListEditorView extends React.Component { static propTypes = { @@ -33,35 +46,33 @@ class LicenseKeyGroupsListEditorView extends React.Component { }; render() { - let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode} = this.props; + let {licenseModelId, vendorName, isReadOnlyMode, isDisplayModal, isModalInEditMode, version} = this.props; let {onAddLicenseKeyGroupClick} = this.props; const {localFilter} = this.state; return ( <div className='license-key-groups-list-editor'> <ListEditorView - title={i18n('License Key Groups for {vendorName} License Model', {vendorName})} + title={i18n('License Key Groups', {vendorName})} plusButtonTitle={i18n('Add License Key Group')} onAdd={onAddLicenseKeyGroupClick} filterValue={localFilter} - onFilter={filter => this.setState({localFilter: filter})} + onFilter={value => this.setState({localFilter: value})} isReadOnlyMode={isReadOnlyMode}> {this.filterList().map(licenseKeyGroup => (this.renderLicenseKeyGroupListItem(licenseKeyGroup, isReadOnlyMode)))} </ListEditorView> - <Modal show={isDisplayModal} bsSize='large' animation={true} className='license-key-groups-modal'> + <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal license-key-groups-modal'> <Modal.Header> <Modal.Title>{`${isModalInEditMode ? i18n('Edit License Key Group') : i18n('Create New License Key Group')}`}</Modal.Title> </Modal.Header> <Modal.Body> { isDisplayModal && ( - <LicenseKeyGroupsEditor licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/> + <LicenseKeyGroupsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={isReadOnlyMode}/> ) } </Modal.Body> </Modal> - <LicenseKeyGroupsConfirmationModal licenseModelId={licenseModelId}/> - </div> ); } @@ -134,5 +145,17 @@ class LicenseKeyGroupsListEditorView extends React.Component { export default LicenseKeyGroupsListEditorView; - - +export function generateConfirmationMsg(licenseKeyGroupToDelete) { + let name = licenseKeyGroupToDelete ? licenseKeyGroupToDelete.name : ''; + let msg = i18n('Are you sure you want to delete "{name}"?', {name}); + let subMsg = licenseKeyGroupToDelete.referencingFeatureGroups + && licenseKeyGroupToDelete.referencingFeatureGroups.length > 0 ? + i18n('This license key group is associated with one or more feature groups') : + ''; + return ( + <div> + <p>{msg}</p> + <p>{subMsg}</p> + </div> + ); +} diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js index 54ce4e3955..1f0a64e295 100644 --- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListReducer.js @@ -1,23 +1,18 @@ -/*- - * ============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 - * + * + * 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========================================================= + * 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. */ - import {actionTypes} from './LicenseKeyGroupsConstants.js'; export default (state = [], action) => { switch (action.type) { diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverview.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverview.js new file mode 100644 index 0000000000..1ca4f37988 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverview.js @@ -0,0 +1,163 @@ +/*! + * 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. + */ +import {connect} from 'react-redux'; +import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js'; +import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js'; +import LicenseModelOverviewView from './LicenseModelOverviewView.jsx'; +import {overviewEditorHeaders, selectedButton} from './LicenseModelOverviewConstants.js'; +import licenseModelOverviewActionHelper from './licenseModelOverviewActionHelper.js'; + +export const mapStateToProps = ({licenseModel: {licenseModelEditor, entitlementPool, licenseAgreement, featureGroup, licenseKeyGroup, licenseModelOverview}}) => { + + let modalHeader, licensingDataList; + let isDisplayModal = false; + + const reduceLicenseKeyGroups = (accum, licenseKeyGroupId) => { + let curLicenseKeyGroup = licenseKeyGroup.licenseKeyGroupsList.find(item => {return item.id === licenseKeyGroupId;}); + if (curLicenseKeyGroup) { + accum.push({ + ...curLicenseKeyGroup, + itemType: overviewEditorHeaders.LICENSE_KEY_GROUP + }); + } + return accum; + }; + + const reduceEntitlementPools = (accum, entitlementPoolId) => { + let curEntitlementPool = entitlementPool.entitlementPoolsList.find(item => {return item.id === entitlementPoolId;}); + if (curEntitlementPool) { + accum.push ({ + ...curEntitlementPool, + itemType: overviewEditorHeaders.ENTITLEMENT_POOL + }); + } + return accum; + }; + + const reduceFeatureGroups = (accum, featureGroupId) => { + let curFeatureGroup = featureGroup.featureGroupsList.find(item => {return item.id === featureGroupId;}); + if (curFeatureGroup) { + let {entitlementPoolsIds = [], licenseKeyGroupsIds = []} = curFeatureGroup; + accum.push({ + ...curFeatureGroup, + itemType: overviewEditorHeaders.FEATURE_GROUP, + children: [ + ...entitlementPoolsIds.length ? entitlementPoolsIds.reduce(reduceEntitlementPools, []) : [], + ...licenseKeyGroupsIds.length ? licenseKeyGroupsIds.reduce(reduceLicenseKeyGroups, []) : [] + ] + }); + } + return accum; + }; + + + const checkEP = (accum, elem) => { + if (!elem.referencingFeatureGroups || !elem.referencingFeatureGroups.length) { + accum.push({ + ...elem, + itemType: overviewEditorHeaders.ENTITLEMENT_POOL + }); + } + return accum; + }; + + const checkLG = (accum, elem) => { + if (!elem.referencingFeatureGroups || !elem.referencingFeatureGroups.length) { + accum.push({ + ...elem, + itemType: overviewEditorHeaders.LICENSE_KEY_GROUP + }); + } + return accum; + }; + + const checkFG = (accum, elem) => { + if (!elem.referencingLicenseAgreements || !elem.referencingLicenseAgreements.length) { + let {entitlementPoolsIds = [], licenseKeyGroupsIds = []} = elem; + accum.push({ + ...elem, + itemType: overviewEditorHeaders.FEATURE_GROUP, + + children: [ + ...entitlementPoolsIds.length ? entitlementPoolsIds.reduce(reduceEntitlementPools, []) : [], + ...licenseKeyGroupsIds.length ? licenseKeyGroupsIds.reduce(reduceLicenseKeyGroups, []) : [] + ] + + }); + } + return accum; + }; + + + + const mapLicenseAgreementData = licenseAgreement => { + let {featureGroupsIds = []} = licenseAgreement; + return { + ...licenseAgreement, + itemType: overviewEditorHeaders.LICENSE_AGREEMENT, + children: featureGroupsIds.length ? featureGroupsIds.reduce(reduceFeatureGroups, []) : [] + }; + }; + + if (entitlementPool.entitlementPoolEditor && entitlementPool.entitlementPoolEditor.data) { + modalHeader = overviewEditorHeaders.ENTITLEMENT_POOL; + isDisplayModal = true; + }else + if (licenseAgreement.licenseAgreementEditor && licenseAgreement.licenseAgreementEditor.data) { + modalHeader = overviewEditorHeaders.LICENSE_AGREEMENT; + isDisplayModal = true; + }else + if (featureGroup.featureGroupEditor && featureGroup.featureGroupEditor.data) { + modalHeader = overviewEditorHeaders.FEATURE_GROUP; + isDisplayModal = true; + }else + if (licenseKeyGroup.licenseKeyGroupsEditor && licenseKeyGroup.licenseKeyGroupsEditor.data) { + modalHeader = overviewEditorHeaders.LICENSE_KEY_GROUP; + isDisplayModal = true; + } + + if (licenseModelOverview.selectedTab === selectedButton.NOT_IN_USE) { + licensingDataList = [ + ...featureGroup.featureGroupsList.reduce(checkFG, []), + ...entitlementPool.entitlementPoolsList.reduce(checkEP, []), + ...licenseKeyGroup.licenseKeyGroupsList.reduce(checkLG, []) + ]; + }else { + licensingDataList = licenseAgreement.licenseAgreementList && licenseAgreement.licenseAgreementList.length ? licenseAgreement.licenseAgreementList.map(mapLicenseAgreementData) : []; + } + + return { + isReadOnlyMode: VersionControllerUtils.isReadOnly(licenseModelEditor.data), + isDisplayModal, + modalHeader, + licenseModelId: licenseModelEditor.data.id, + version: licenseModelEditor.data.version, + licensingDataList, + selectedTab: licenseModelOverview.selectedTab + + }; +}; + +const mapActionsToProps = (dispatch, {licenseModelId}) => { + return { + onCallVCAction: action => { + LicenseModelActionHelper.performVCAction(dispatch, {licenseModelId, action}); + }, + onTabSelect: (buttonTab) => licenseModelOverviewActionHelper.selectVLMListView(dispatch,{buttonTab}) + }; +}; + +export default connect(mapStateToProps, mapActionsToProps)(LicenseModelOverviewView); diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js new file mode 100644 index 0000000000..b5a27ed018 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js @@ -0,0 +1,42 @@ +/*! + * 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. + */ +import keyMirror from 'nfvo-utils/KeyMirror.js'; + +export const overviewItems = keyMirror({ + LICENSE_AGREEMENTS: 'License Agreements', + FEATURE_GROUPS: 'Feature Groups', + ENTITLEMENT_POOLS: 'Entitlement Pools', + LICENSE_KEY_GROUPS: 'License Key Groups' +}); + +export const overviewEditorHeaders = keyMirror({ + LICENSE_AGREEMENT: 'License Agreement', + FEATURE_GROUP: 'Feature Group', + ENTITLEMENT_POOL: 'Entitlement Pool', + LICENSE_KEY_GROUP: 'License Key Group' +}); + +export const actionTypes = keyMirror({ + LICENSE_MODEL_OVERVIEW_TAB_SELECTED: null, + LM_DATA_CHANGED: null +}); + +export const selectedButton = keyMirror({ + VLM_LIST_VIEW: null, + NOT_IN_USE: null +}); + +export const VLM_DESCRIPTION_FORM = 'VLMDEWSCRIPTIONFORM'; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx new file mode 100644 index 0000000000..d6c79ddb52 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx @@ -0,0 +1,105 @@ +/*! + * 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. + */ +import React from 'react'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import Modal from 'nfvo-components/modal/Modal.jsx'; +import classNames from 'classnames'; + +import EntitlementPoolsEditor from '../entitlementPools/EntitlementPoolsEditor.js'; +import FeatureGroupEditor from '../featureGroups/FeatureGroupEditor.js'; +import LicenseAgreementEditor from '../licenseAgreement/LicenseAgreementEditor.js'; +import LicenseKeyGroupsEditor from '../licenseKeyGroups/LicenseKeyGroupsEditor.js'; +import {overviewEditorHeaders, selectedButton} from './LicenseModelOverviewConstants.js'; + +import SummaryView from './SummaryView.jsx'; +import VLMListView from './VLMListView.jsx'; +import ListButtons from './summary/ListButtons.jsx'; + + +const setModalClassName = (modalHeader) => { + switch (modalHeader) { + case overviewEditorHeaders.ENTITLEMENT_POOL: + return 'entitlement-pools-modal'; + case overviewEditorHeaders.LICENSE_AGREEMENT: + return 'license-agreement-modal'; + case overviewEditorHeaders.FEATURE_GROUP: + return 'feature-group-modal'; + case overviewEditorHeaders.LICENSE_KEY_GROUP: + return 'license-key-groups-modal'; + default: + return ''; + } +}; + +class LicenseModelOverviewView extends React.Component { + + static propTypes = { + isDisplayModal: React.PropTypes.bool, + isReadOnlyMode: React.PropTypes.bool, + licenseModelId: React.PropTypes.string, + licensingDataList: React.PropTypes.array, + modalHeader: React.PropTypes.string, + selectedTab: React.PropTypes.symbol, + onTabSelect: React.PropTypes.func, + onCallVCAction: React.PropTypes.func, + onClose: React.PropTypes.func + }; + + render() { + let {isDisplayModal, modalHeader, licensingDataList, selectedTab, onTabSelect} = this.props; + let selectedInUse = selectedTab !== selectedButton.NOT_IN_USE; + + return( + <div className='license-model-overview'> + <SummaryView/> + <div className={classNames('overview-list-section ', !selectedInUse ? 'overview-list-orphans' : '' )}> + <div className='vlm-list-tab-panel'> + <div className='section-title'>{selectedInUse ? i18n('VLM List View') : i18n('Entities not in Use')}</div> + <ListButtons onTabSelect={onTabSelect} selectedInUse={selectedInUse}/> + </div> + <VLMListView licensingDataList={licensingDataList} showInUse={selectedInUse}/> + </div> + { + isDisplayModal && + <Modal show={isDisplayModal} bsSize='large' animation={true} className={classNames('onborading-modal', setModalClassName(modalHeader))}> + <Modal.Header> + <Modal.Title>{`${i18n('Create New ')}${i18n(modalHeader)}`}</Modal.Title> + </Modal.Header> + <Modal.Body> + {this.renderModalBody(modalHeader)} + </Modal.Body> + </Modal> + } + </div> + ); + } + + renderModalBody(modalHeader) { + let {licenseModelId, version} = this.props; + switch (modalHeader) { + case overviewEditorHeaders.ENTITLEMENT_POOL: + return <EntitlementPoolsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={false}/>; + case overviewEditorHeaders.LICENSE_AGREEMENT: + return <LicenseAgreementEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={false}/>; + case overviewEditorHeaders.FEATURE_GROUP: + return <FeatureGroupEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={false}/>; + case overviewEditorHeaders.LICENSE_KEY_GROUP: + return <LicenseKeyGroupsEditor version={version} licenseModelId={licenseModelId} isReadOnlyMode={false}/>; + } + } +} + +export default LicenseModelOverviewView; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/SummaryView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/SummaryView.jsx new file mode 100644 index 0000000000..6fcdb477e6 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/SummaryView.jsx @@ -0,0 +1,33 @@ +/*! + * 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. + */ +import React from 'react'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import {default as VendorDataView} from './summary/VendorDataView.js'; +import {default as SummaryCountList} from './summary/SummaryCountList.js'; + +function SummaryView() { + return( + <div className='overview-top-section'> + <div className='overview-title'>{i18n('overview')}</div> + <div className='license-model-overview-top'> + <VendorDataView/> + <SummaryCountList/> + </div> + </div> + ); +} + +export default SummaryView; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx new file mode 100644 index 0000000000..119008a849 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx @@ -0,0 +1,123 @@ +/*! + * 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. + */ +import React, {Component} from 'react'; +import {Collapse} from 'react-bootstrap'; +import LicenseAgreement from './listItems/LicenseAgreement.jsx'; +import EntitlementPool from './listItems/EntitlementPool.jsx'; +import FeatureGroup from './listItems/FeatureGroup.jsx'; +import LicenseKeyGroup from './listItems/LicenseKeyGroup.jsx'; +import {overviewEditorHeaders} from './LicenseModelOverviewConstants.js'; + +class VLMListView extends Component { + + static propTypes = { + licensingDataList: React.PropTypes.array, + showInUse: React.PropTypes.bool + }; + + state = { + + }; + + render() { + let {licensingDataList = []} = this.props; + return ( + <div className='vlm-list-view'> + <div> + <ul className='vlm-list' data-test-id='vlm-list'> + {licensingDataList.map(item => this.renderLicensingItem(item))} + </ul> + </div> + </div> + ); + } + + renderLicensingItem(item) { + switch (item.itemType) { + case overviewEditorHeaders.LICENSE_AGREEMENT : + return this.renderLicenseAgreementItem(item); + case overviewEditorHeaders.FEATURE_GROUP : + return this.renderFeatureGroupItem(item); + case overviewEditorHeaders.LICENSE_KEY_GROUP : + return this.renderLicenseKeyGroupItem(item); + case overviewEditorHeaders.ENTITLEMENT_POOL: + return this.renderEntitlementPoolItem(item); + default: + return; + } + } + + renderLicenseAgreementItem(licenseAgreement) { + return ( + <li key={licenseAgreement.id}> + <LicenseAgreement + laData={licenseAgreement} + isCollapsed={this.state[licenseAgreement.id]} + onClick={event => this.updateCollapsable(event, licenseAgreement.id) }/> + <Collapse in={this.state[licenseAgreement.id]}> + <ul> + {licenseAgreement.children && licenseAgreement.children.map(item => this.renderLicensingItem(item))} + </ul> + </Collapse> + </li> + ); + } + + renderFeatureGroupItem(featureGroup) { + const {showInUse} = this.props; + return ( + <li key={featureGroup.id}> + <FeatureGroup + fgData={featureGroup} + isCollapsed={this.state[featureGroup.id]} + onClick={event=> this.updateCollapsable(event, featureGroup.id) }/> + { + showInUse && <Collapse in={this.state[featureGroup.id]}> + <ul> + {featureGroup.children && featureGroup.children.map(item => this.renderLicensingItem(item))} + + </ul> + </Collapse> + } + </li> + ); + } + + renderEntitlementPoolItem(entitlementPool) { + return ( + <li key={entitlementPool.id}> + <EntitlementPool epData={entitlementPool} /> + </li> + ); + } + + renderLicenseKeyGroupItem(licenseKeyGroup) { + return ( + <li key={licenseKeyGroup.id}> + <LicenseKeyGroup lkgData={licenseKeyGroup} /> + </li> + ); + } + + updateCollapsable(event, id) { + event.stopPropagation(); + let obj = {}; + obj[id] = !this.state[id]; + this.setState(obj); + } +} + +export default VLMListView; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js new file mode 100644 index 0000000000..f0286ba3bb --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js @@ -0,0 +1,39 @@ +/*! + * 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. + */ +import {actionTypes} from './LicenseModelOverviewConstants.js'; + +export default { + selectVLMListView(dispatch, {buttonTab}) { + dispatch({ + type: actionTypes.LICENSE_MODEL_OVERVIEW_TAB_SELECTED, + buttonTab + }); + }, + + editDescriptionOpen(dispatch, {description}) { + dispatch({ + type: actionTypes.LM_DATA_CHANGED, + description + }); + }, + + editDescriptionClose(dispatch) { + dispatch({ + type: actionTypes.LM_DATA_CHANGED, + description: false + }); + } +}; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx new file mode 100644 index 0000000000..94977b40d1 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx @@ -0,0 +1,53 @@ +/*! + * 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. + */ +import React, {Component} from 'react'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import {extractValue, extractUnits} from '../../entitlementPools/EntitlementPoolsConstants.js'; +import ArrowCol from './listItemsComponents/ArrowCol.jsx'; +import ItemInfo from './listItemsComponents/ItemInfo.jsx'; +import IconCol from './listItemsComponents/IconCol.jsx'; +import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx'; + +class EntitlementPool extends Component { + render() { + let {epData: {name, description, manufacturerReferenceNumber}} = this.props; + return ( + <div className='vlm-list-item vlm-list-item-ep' data-test-id='vlm-list-item-ep'> + <ArrowCol/> + <IconCol className='ep-icon'/> + <ItemInfo name={name} description={description}/> + <AdditionalDataCol> + <AdditionalDataElement + className='vlm-list-item-entitlement-metric' + name={i18n('Entitlement')} + value={this.getEntitlement()}/> + <AdditionalDataElement + name={i18n('Manufacturer Reference Number')} + value={manufacturerReferenceNumber} + className='vlm-list-item-sku'/> + </AdditionalDataCol> + </div> + ); + } + + getEntitlement() { + let {epData: {entitlementMetric, aggregationFunction, time, thresholdValue, thresholdUnits}} = this.props; + return `${extractValue(aggregationFunction)} ${extractValue(entitlementMetric)} per ${extractValue(time)} ${thresholdValue} ${extractUnits(thresholdUnits)}`; + } + +} + +export default EntitlementPool; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx new file mode 100644 index 0000000000..8dbd46a29e --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx @@ -0,0 +1,50 @@ +/*! + * 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. + */ +import React, {Component} from 'react'; +import {overviewEditorHeaders} from '../LicenseModelOverviewConstants.js'; +import ArrowCol from './listItemsComponents/ArrowCol.jsx'; +import ItemInfo from './listItemsComponents/ItemInfo.jsx'; +import IconCol from './listItemsComponents/IconCol.jsx'; + +class FeatureGroup extends Component { + render() { + let {fgData: {name, description, children = []}, isCollapsed, onClick} = this.props; + return ( + <div onClick={e => onClick(e)} className='vlm-list-item vlm-list-item-fg' data-test-id='vlm-list-item-fg'> + <ArrowCol isCollapsed={isCollapsed} length={children.length} /> + <IconCol className='fg-icon'/> + <ItemInfo name={name} description={description}> + <div className='children-count'> + <span className='count-value'> + Entitlement Pools: + <span data-test-id='vlm-list-ep-count-value'> + {`${children.filter(child => child.itemType === overviewEditorHeaders.ENTITLEMENT_POOL).length}`} + </span> + </span> + <span className='count-value'> + License Key Groups: + <span data-test-id='vlm-list-lkg-count-value'> + {`${children.filter(child => child.itemType === overviewEditorHeaders.LICENSE_KEY_GROUP).length}`} + </span> + </span> + </div> + </ItemInfo> + </div> + ); + } +} + +export default FeatureGroup; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx new file mode 100644 index 0000000000..dd4686d330 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx @@ -0,0 +1,53 @@ +/*! + * 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. + */ +import React, {Component} from 'react'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx'; +import {optionsInputValues} from '../../licenseAgreement/LicenseAgreementConstants.js'; +import ArrowCol from './listItemsComponents/ArrowCol.jsx'; +import ItemInfo from './listItemsComponents/ItemInfo.jsx'; +import IconCol from './listItemsComponents/IconCol.jsx'; +import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx'; + +class LicenseAgreement extends Component { + render() { + let {laData: {name, description, licenseTerm, children = []}, isCollapsed, onClick} = this.props; + return ( + <div onClick={e => onClick(e)} className='vlm-list-item vlm-list-item-la' data-test-id='vlm-list-la-item'> + <ArrowCol isCollapsed={isCollapsed} length={children.length} /> + <IconCol className='la-icon'/> + <ItemInfo name={name} description={description}> + <div className='children-count'> + <span className='count-value'>Feature Groups: <span data-test-id='vlm-list-fg-count-value'>{`${children.length}`}</span></span> + </div> + </ItemInfo> + <AdditionalDataCol> + <AdditionalDataElement + name={i18n('License Model Type')} + value={this.extractValue(licenseTerm)}/> + </AdditionalDataCol> + </div> + ); + } + + 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 LicenseAgreement; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx new file mode 100644 index 0000000000..9722b83336 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx @@ -0,0 +1,48 @@ +/*! + * 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. + */ +import React, {Component} from 'react'; +import i18n from 'nfvo-utils/i18n/i18n.js'; +import {extractValue, getOperationalScopes} from '../../licenseKeyGroups/LicenseKeyGroupsConstants.js'; +import ArrowCol from './listItemsComponents/ArrowCol.jsx'; +import ItemInfo from './listItemsComponents/ItemInfo.jsx'; +import IconCol from './listItemsComponents/IconCol.jsx'; +import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx'; + +class LicenseKeyGroup extends Component { + render() { + let {lkgData: {name, description, operationalScope, type}} = this.props; + return ( + <div className='vlm-list-item vlm-list-item-lkg' data-test-id='vlm-list-item-lkg'> + <ArrowCol/> + <IconCol className='lkg-icon'/> + <ItemInfo name={name} description={description}/> + <AdditionalDataCol> + <AdditionalDataElement + className='vlm-list-item-operational-scope' + name={i18n('Operational Scope')} + value={operationalScope && getOperationalScopes(operationalScope)}/> + <AdditionalDataElement + className='vlm-list-item-group-type' + name={i18n('Type')} + value={extractValue(type)}/> + </AdditionalDataCol> + </div> + ); + } + +} + +export default LicenseKeyGroup; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/AdditionalDataCol.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/AdditionalDataCol.jsx new file mode 100644 index 0000000000..5b5daafb4f --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/AdditionalDataCol.jsx @@ -0,0 +1,51 @@ +/*! + * 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. + */ +import React from 'react'; + +function AdditionalDataCol({children}) { + return ( + <div className='list-item-section list-item-additional-data-col'> + <div className='additional-data-col-border'></div> + <div className='additional-data'> + {children} + </div> + </div> + ); +} + +AdditionalDataCol.propTypes = { + children: React.PropTypes.oneOfType([ + React.PropTypes.arrayOf(React.PropTypes.node), + React.PropTypes.node + ]) +}; + +function AdditionalDataElement({className, name, value}) { + return ( + <div className={className}> + <span className='additional-data-name'>{name}: </span> + <span className='additional-data-value'>{value}</span> + </div> + ); +} + +AdditionalDataElement.propTypes = { + name: React.PropTypes.string, + value: React.PropTypes.string, + className: React.PropTypes.string +}; + +export {AdditionalDataCol, AdditionalDataElement}; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ArrowCol.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ArrowCol.jsx new file mode 100644 index 0000000000..a5eb9d27dd --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ArrowCol.jsx @@ -0,0 +1,35 @@ +/*! + * 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. + */ +import React from 'react'; +import classNames from 'classnames'; + +function ArrowCol ({isCollapsed, length}) { + return ( + <div className='list-item-section list-item-arrow-col'> + <div className={classNames('arrow-icon', {'chevron': length > 0}, + {'down': (length > 0 && isCollapsed)}, + {'right': (length > 0 && (!isCollapsed))})} > + </div> + </div> + ); +} + +ArrowCol.propTypes = { + isCollapsed: React.PropTypes.bool, + length: React.PropTypes.number +}; + +export default ArrowCol; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/IconCol.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/IconCol.jsx new file mode 100644 index 0000000000..7fd7fcb88a --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/IconCol.jsx @@ -0,0 +1,26 @@ +/*! + * 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. + */ +import React from 'react'; + +function IconCol({className}) { + return ( + <div className='list-item-section list-item-icon-col'> + <div className={className}></div> + </div> + ); +} + +export default IconCol; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ItemInfo.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ItemInfo.jsx new file mode 100644 index 0000000000..655a0dd4a8 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/ItemInfo.jsx @@ -0,0 +1,39 @@ +/*! + * 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. + */ +import React from 'react'; + +function ItemInfo({name, description, children}) { + return ( + <div className='list-item-section vlm-item-info'> + <div className='vlm-list-item-title'> + <div className='item-name' data-test-id='vlm-list-item-name'>{name}</div> + {children} + </div> + <div className='vlm-list-item-description'>{description}</div> + </div> + ); +} + +ItemInfo.propTypes = { + name: React.PropTypes.string, + description: React.PropTypes.string, + children: React.PropTypes.oneOfType([ + React.PropTypes.arrayOf(React.PropTypes.node), + React.PropTypes.node + ]) +}; + +export default ItemInfo; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/LicenseModelDescriptionEdit.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/LicenseModelDescriptionEdit.jsx new file mode 100644 index 0000000000..0c0103fc10 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/LicenseModelDescriptionEdit.jsx @@ -0,0 +1,56 @@ +/*! + * 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. + */ +import React from 'react'; +import Input from 'nfvo-components/input/validation/Input.jsx'; + +class LicenseModelDescriptionEdit extends React.Component { + render() { + let {onDataChanged, description, genericFieldInfo} = this.props; + let saveButtonClassName = (genericFieldInfo.description.isValid) ? 'description-save' : 'description-save disabled'; + return( + <div className='vendor-description-edit'> + + <Input + onChange={description => onDataChanged({description})} + value={description} + isValid={genericFieldInfo.description.isValid} + errorText={genericFieldInfo.description.errorText} + className='description-edit-textarea' + type='textarea'/> + <div className='buttons-row'> + <div className='buttons-wrapper'> + <div onClick={() => this.onClose()} className='description-button' data-test-id='vlm-summary-vendor-desc-cancel-btn'>cancel</div> + <div onClick={() => this.submit()} className={saveButtonClassName} data-test-id='vlm-summary-vendor-desc-save-btn'>save</div> + </div> + </div> + </div> + ); + } + + onClose() { + this.props.onClose(); + } + + submit() { + let {onSubmit, data, description} = this.props; + onSubmit({ + ...data, + description: description + }); + } +} + +export default LicenseModelDescriptionEdit; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx new file mode 100644 index 0000000000..730ccb33f1 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx @@ -0,0 +1,39 @@ +/*! + * 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. + */ +import React from 'react'; +import {selectedButton} from '../LicenseModelOverviewConstants.js'; + +function ListButtons ({onTabSelect, selectedInUse}) { + return ( + <div className='overview-buttons-section'> + <div onClick={()=>onTabSelect(selectedButton.VLM_LIST_VIEW)} + className={selectedInUse ? 'button-vlm-list-view vlm-list-icon selected' : 'button-vlm-list-view vlm-list-icon' } + data-test-id='vlm-overview-vlmlist-tab'></div> + <div onClick={()=>onTabSelect(selectedButton.NOT_IN_USE)} + className={selectedInUse ? 'button-vlm-list-view entities-list-icon' : 'button-vlm-list-view entities-list-icon selected' } + data-test-id='vlm-overview-orphans-tab' > + </div> + + </div> + ); +} + +ListButtons.propTypes = { + onTabSelect: React.PropTypes.func, + selectedInUse: React.PropTypes.bool +}; + +export default ListButtons; diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountItem.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountItem.jsx new file mode 100644 index 0000000000..66f2cc6838 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountItem.jsx @@ -0,0 +1,31 @@ +/*! + * 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. + */ +import React from 'react'; + +function SummaryCountItem ({name, counter, onAdd, onNavigate, isReadOnlyMode}) { + return( + <div className='summary-count-item'> + <div className='summary-name-and-count' onClick={onNavigate}> + <span className='item-name' onClick={onNavigate}>{name}</span> + <span className='item-count' onClick={onNavigate} data-test-id={'vlm-summary-vendor-counter-' + name.toLowerCase().replace(/\s/g,'-')}>({counter})</span> + </div> + <div className={isReadOnlyMode ? 'add-button disabled' : 'add-button'} onClick={onAdd} data-test-id={'vlm-summary-vendor-add-btn-' + name.toLowerCase().replace(/\s/g,'-')}/> + </div> + ); +} + +export default SummaryCountItem; + diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountList.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountList.js new file mode 100644 index 0000000000..c69a092d23 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/SummaryCountList.js @@ -0,0 +1,126 @@ +/*! + * 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. + */ +import React from 'react'; +import {connect} from 'react-redux'; + +import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js'; + +import OnboardingActionHelper from '../../../OnboardingActionHelper.js'; +import EntitlementPoolsActionHelper from '../../entitlementPools/EntitlementPoolsActionHelper.js'; +import LicenseAgreementActionHelper from '../../licenseAgreement/LicenseAgreementActionHelper.js'; +import LicenseKeyGroupsActionHelper from '../../licenseKeyGroups/LicenseKeyGroupsActionHelper.js'; +import FeatureGroupsActionHelper from '../../featureGroups/FeatureGroupsActionHelper.js'; + +import {overviewItems} from '../LicenseModelOverviewConstants.js'; +import SummaryCountItem from './SummaryCountItem.jsx'; + +export const mapStateToProps = ({licenseModel: {licenseModelEditor, licenseAgreement: {licenseAgreementList}, + featureGroup: {featureGroupsList}, entitlementPool: {entitlementPoolsList}, licenseKeyGroup: {licenseKeyGroupsList}}}) => { + + let {vendorName, description, id, version} = licenseModelEditor.data; + + let isReadOnlyMode = VersionControllerUtils.isReadOnly(licenseModelEditor.data); + + let counts = [ + {name: overviewItems.LICENSE_AGREEMENTS, count: licenseAgreementList.length}, + {name: overviewItems.FEATURE_GROUPS, count: featureGroupsList.length}, + {name: overviewItems.ENTITLEMENT_POOLS, count: entitlementPoolsList.length}, + {name: overviewItems.LICENSE_KEY_GROUPS, count: licenseKeyGroupsList.length}, + ]; + return { + vendorName, + licenseModelId: id, + description, + counts, + isReadOnlyMode, + version + }; +}; + +const mapActionsToProps = (dispatch) => { + return { + onEditorOpenClick: (name, licenseModelId, version) => { + switch (name) { + case overviewItems.ENTITLEMENT_POOLS: + EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch); + break; + case overviewItems.FEATURE_GROUPS: + FeatureGroupsActionHelper.openFeatureGroupsEditor(dispatch, {licenseModelId, version}); + break; + case overviewItems.LICENSE_AGREEMENTS: + LicenseAgreementActionHelper.openLicenseAgreementEditor(dispatch, {licenseModelId, version}); + break; + case overviewItems.LICENSE_KEY_GROUPS: + LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch); + break; + default: + break; + } + }, + onNavigateClick: ({name, licenseModelId, version}) => { + switch (name) { + case overviewItems.ENTITLEMENT_POOLS: + OnboardingActionHelper.navigateToEntitlementPools(dispatch, {licenseModelId, version}); + break; + case overviewItems.FEATURE_GROUPS: + OnboardingActionHelper.navigateToFeatureGroups(dispatch, {licenseModelId, version}); + break; + case overviewItems.LICENSE_AGREEMENTS: + OnboardingActionHelper.navigateToLicenseAgreements(dispatch, {licenseModelId, version}); + break; + case overviewItems.LICENSE_KEY_GROUPS: + OnboardingActionHelper.navigateToLicenseKeyGroups(dispatch, {licenseModelId, version}); + break; + default: + break; + } + } + }; +}; + +export class SummaryCountList extends React.Component { + + render() { + let {counts} = this.props; + return( + <div className='summary-count-list'> + {counts.map(item => this.renderItem(item))} + </div> + ); + } + + renderItem(item){ + const {name, count} = item; + const {isReadOnlyMode} = this.props; + return( + <SummaryCountItem isReadOnlyMode={isReadOnlyMode} name={name} counter={count} onNavigate={() => this.onNavigate(name)} onAdd={() => this.onAdd(name)} key={name} /> + ); + } + + onAdd(name) { + let {onEditorOpenClick, licenseModelId, isReadOnlyMode, version} = this.props; + if (!isReadOnlyMode) { + onEditorOpenClick(name, licenseModelId, version); + } + } + + onNavigate(name) { + let {onNavigateClick, licenseModelId, version} = this.props; + onNavigateClick({licenseModelId, name, version}); + } +} + +export default connect(mapStateToProps, mapActionsToProps)(SummaryCountList); diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js new file mode 100644 index 0000000000..1d65ab9869 --- /dev/null +++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js @@ -0,0 +1,86 @@ +/*! + * 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. + */ +import React from 'react'; +import {connect} from 'react-redux'; + +import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js'; +import licenseModelOverviewActionHelper from '../licenseModelOverviewActionHelper.js'; +import LicenseModelActionHelper from '../../LicenseModelActionHelper.js'; +import LicenseModelDescriptionEdit from './LicenseModelDescriptionEdit.jsx'; +import VersionControllerUtils from 'nfvo-components/panel/versionController/VersionControllerUtils.js'; +import {VLM_DESCRIPTION_FORM} from '../LicenseModelOverviewConstants.js'; + +export const mapStateToProps = ({licenseModel: {licenseModelEditor: {data}, licenseModelOverview: {descriptionEditor: {data: descriptionData, genericFieldInfo} }}}) => { + let description = (descriptionData && descriptionData.description) ? descriptionData.description : null; + let isReadOnlyMode = VersionControllerUtils.isReadOnly(data); + return { + data, + description, + genericFieldInfo, + isReadOnlyMode + }; +}; + +const mapActionsToProps = (dispatch) => { + return { + onDataChanged: (deltaData) => ValidationHelper.dataChanged(dispatch, {deltaData, formName: VLM_DESCRIPTION_FORM}), + onCancel: () => licenseModelOverviewActionHelper.editDescriptionClose(dispatch), + onSubmit: (licenseModel) => { + licenseModelOverviewActionHelper.editDescriptionClose(dispatch); + LicenseModelActionHelper.saveLicenseModel(dispatch, {licenseModel}); + }, + onVendorDescriptionEdit: description => licenseModelOverviewActionHelper.editDescriptionOpen(dispatch,{description}) + }; +}; + + + +export class VendorDataView extends React.Component { + render() { + let {data: {vendorName}, description, isReadOnlyMode} = this.props; + return ( + <div className='vendor-data-view'> + <div className='vendor-title'>vendor</div> + <div className='vendor-name' data-test-id='vlm-summary-vendor-name'>{vendorName}</div> + { + description && !isReadOnlyMode ? this.renderDescriptionEdit() : this.renderDescription() + } + </div> + ); + } + + renderDescription() { + let {data: {description}, onVendorDescriptionEdit, isReadOnlyMode} = this.props; + return ( + <div onClick={() => {if (!isReadOnlyMode) {onVendorDescriptionEdit(description);}}} className={!isReadOnlyMode ? 'vendor-description' : 'vendor-description-readonly'}> + <div className='description-data' data-test-id='vlm-summary-vendor-description'> + {description} + </div> + </div> + ); + } + + renderDescriptionEdit() { + let {onCancel, onDataChanged, onSubmit, description, genericFieldInfo, data} = this.props; + return( + <LicenseModelDescriptionEdit onClose={onCancel} onDataChanged={onDataChanged} onSubmit={onSubmit} data={data} genericFieldInfo={genericFieldInfo} description={description}/> + ); + } + +} + +export default connect(mapStateToProps, mapActionsToProps)(VendorDataView); + |