aboutsummaryrefslogtreecommitdiffstats
path: root/openecomp-ui
diff options
context:
space:
mode:
authorAvi Ziv <AVIZI@amdocs.com>2017-07-26 17:37:57 +0300
committerAvi Ziv <avi.ziv@amdocs.com>2017-07-26 18:27:22 +0300
commit61070c9c6b665fdea79b3ccdfeafc3a6b50d262e (patch)
treedfe9c169cfac91d6c72ac9ff23375f2aafac6405 /openecomp-ui
parentb824a997e19f6ee9627cb1b1e124c756bd8183fc (diff)
[SDC] Full OnBoard health-check and NFoD support
Change-Id: I606f8a52c7e6d2bd5558f824957d890e552c5423 Signed-off-by: Avi Ziv <avi.ziv@amdocs.com>
Diffstat (limited to 'openecomp-ui')
-rw-r--r--openecomp-ui/.gitignore3
-rw-r--r--openecomp-ui/devConfig.defaults.json2
-rw-r--r--openecomp-ui/package.json9
-rw-r--r--openecomp-ui/proxy-server.js92
-rw-r--r--openecomp-ui/resources/scss/_modules.scss1
-rw-r--r--openecomp-ui/resources/scss/bootstrap-cust/_modals.scss1
-rw-r--r--openecomp-ui/resources/scss/common/_utils.scss21
-rw-r--r--openecomp-ui/resources/scss/components/_datepicker.scss34
-rw-r--r--openecomp-ui/resources/scss/components/_dualListBox.scss3
-rw-r--r--openecomp-ui/resources/scss/components/_notifications.scss6
-rw-r--r--openecomp-ui/resources/scss/components/_selectActionTable.scss11
-rw-r--r--openecomp-ui/resources/scss/components/_validationForm.scss6
-rw-r--r--openecomp-ui/resources/scss/modules/_entitlementPools.scss28
-rw-r--r--openecomp-ui/resources/scss/modules/_featureGroup.scss8
-rw-r--r--openecomp-ui/resources/scss/modules/_licenseKeyGroup.scss20
-rw-r--r--openecomp-ui/resources/scss/modules/_licenseModel.scss61
-rw-r--r--openecomp-ui/resources/scss/modules/_licenseModelLimits.scss121
-rw-r--r--openecomp-ui/resources/scss/modules/_licenseModelOverview.scss366
-rw-r--r--openecomp-ui/resources/scss/modules/onboardingCatalog/_catalogTile.scss8
-rw-r--r--openecomp-ui/resources/scss/modules/onboardingCatalog/_vendorTile.scss5
-rw-r--r--openecomp-ui/resources/scss/onboarding.scss110
-rw-r--r--openecomp-ui/runLocalFE.cmd38
-rw-r--r--openecomp-ui/runLocalFE.js104
-rw-r--r--openecomp-ui/src/index.html2
-rw-r--r--openecomp-ui/src/nfvo-components/datepicker/Datepicker.jsx8
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx3
-rw-r--r--openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx17
-rw-r--r--openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx2
-rw-r--r--openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js2
-rw-r--r--openecomp-ui/src/nfvo-components/table/SelectActionTable.jsx2
-rw-r--r--openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx4
-rw-r--r--openecomp-ui/src/nfvo-utils/Validator.js5
-rw-r--r--openecomp-ui/src/nfvo-utils/getValue.js32
-rw-r--r--openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js7
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js19
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx16
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js14
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelValidations.js41
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js84
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js17
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js17
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx346
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsLimits.js56
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx15
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx36
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx14
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js8
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js4
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx13
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js88
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js10
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js16
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js44
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx254
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsLimits.js57
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx14
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.js25
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.jsx193
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorActionHelper.js (renamed from openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageNavigationReducer.js)24
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js52
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorReducer.js70
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/Limits.jsx108
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitsServer.js46
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js8
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx7
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx10
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx24
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx23
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx15
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx12
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/listItemsComponents/IconCol.jsx4
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx29
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js35
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js12
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js3
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js12
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js31
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js3
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx4
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js7
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx9
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx5
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditor.js2
-rw-r--r--openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx2
-rw-r--r--openecomp-ui/test-utils/factories/licenseModel/EntitlementPoolFactories.js12
-rw-r--r--openecomp-ui/test-utils/factories/licenseModel/LimitFactories.js38
-rw-r--r--openecomp-ui/test/licenseModel/entitlementPools/test.js170
-rw-r--r--openecomp-ui/test/licenseModel/licenseKeyGroups/test.js169
103 files changed, 2474 insertions, 1079 deletions
diff --git a/openecomp-ui/.gitignore b/openecomp-ui/.gitignore
index 2a11210d95..13e532c095 100644
--- a/openecomp-ui/.gitignore
+++ b/openecomp-ui/.gitignore
@@ -6,6 +6,9 @@ debug.log
dist
node_modules
devConfig.json
+proxy-server.js
+runLocalFE.cmd
+runLocalFE.js
.npmrc
test/coverage
npm-debug.log
diff --git a/openecomp-ui/devConfig.defaults.json b/openecomp-ui/devConfig.defaults.json
index 46f0d189e8..99380b1e50 100644
--- a/openecomp-ui/devConfig.defaults.json
+++ b/openecomp-ui/devConfig.defaults.json
@@ -1,6 +1,6 @@
{
"port": 9000,
- "proxyATTTarget": null,
+ "proxyCatalogTarget": null,
"proxyTarget": null,
"bundles": {
"bundle": ["sdc-app/sdc.app.jsx"],
diff --git a/openecomp-ui/package.json b/openecomp-ui/package.json
index 0e1e66b80e..ef44bfb2b8 100644
--- a/openecomp-ui/package.json
+++ b/openecomp-ui/package.json
@@ -8,8 +8,8 @@
"start": "gulp dev && webpack-dev-server --progress",
"build": "gulp build",
"css-usage": "gulp css-usage",
- "static-keys-bundle" : "gulp static-keys-bundle",
- "check-keys-against-bundles" : "gulp static-keys-bundle-with-report",
+ "static-keys-bundle": "gulp static-keys-bundle",
+ "check-keys-against-bundles": "gulp static-keys-bundle-with-report",
"test": "jest",
"test-failedTestReport": "jest --json | node test-utils/failedTestReport.js",
"test-dev": "jest --watch",
@@ -18,9 +18,10 @@
"storyshots": "jest storyshots.test.js",
"build-storybook": "build-storybook -c .storybook -o .storybook-dist && gulp copy-storybook-fonts && gulp copy-storybook-resources-prod"
},
- "dependencies": {
+ "dependencies": {
"classnames": "^2.2.5",
"core-js": "^2.4.0",
+ "d3": "^3.5.16",
"dox-sequence-diagram-ui": "file:../dox-sequence-diagram-ui",
"intl": "^1.0.1",
"intl-format-cache": "^2.0.5",
@@ -39,7 +40,7 @@
"react-sortable": "^1.2.0",
"redux": "^3.3.1",
"restful-js": "^0.7.0",
- "sdc-ui": "^1.5.12",
+ "sdc-ui": "1.6.0",
"uuid-js": "^0.7.5",
"validator": "^4.3.0"
},
diff --git a/openecomp-ui/proxy-server.js b/openecomp-ui/proxy-server.js
deleted file mode 100644
index 4733d38a89..0000000000
--- a/openecomp-ui/proxy-server.js
+++ /dev/null
@@ -1,92 +0,0 @@
-'use strict';
-
-const proxy = require('http-proxy-middleware');
-
-let localDevConfig = {};
-try {
- localDevConfig = require('./devConfig');
-} catch (e) {}
-const devConfig = Object.assign({}, require('./devConfig.defaults'), localDevConfig);
-let devPort = process.env.PORT || devConfig.port;
-
-let jsonConfig = {
- "appContextPath" : "/onboarding"
-};
-
-try {
- jsonConfig = require('./src/sdc-app/config/config.json');
-} catch (e) {
- console.log('could not load config. using deault value instead');
-}
-
-module.exports = function (server) {
- let proxyConfigDefaults = {
- changeOrigin: true,
- secure: false,
- onProxyRes: (proxyRes, req, res) => {
- let setCookie = proxyRes.headers['set-cookie'];
- if (setCookie) {
- setCookie[0] = setCookie[0].replace(/\bSecure\b(; )?/, '');
- }
- if (proxyRes.statusCode === 302 && proxyRes.headers.location.indexOf('login') > -1) {
- proxyRes.headers.location = `http://localhost:${devPort}/sdc1#/onboardVendor`;
- res.setHeader('Set-Cookie', [
- 'HTTP_CSP_EMAIL=csantana@sdc.com',
- 'HTTP_CSP_FIRSTNAME=Carlos',
- 'HTTP_CSP_LASTNAME=Santana',
- 'HTTP_CSP_WSTYPE=Intranet',
- 'HTTP_IV_REMOTE_ADDRESS=0.0.0.0',
- 'HTTP_IV_USER=cs0008',
- 'USER_ID=cs0008'
- ]);
- }
- }
- };
-
- let middlewares = [
- (req, res, next) => {
- if (req.url.indexOf('/proxy-designer1') > -1) {
- req.url = req.url.replace('/proxy-designer1', '');
- }
-
- if (req.url.indexOf(jsonConfig.appContextPath + '/resources') > -1) {
- req.url = req.url.replace(jsonConfig.appContextPath, '');
- }
-
- let match = req.url.match(/^(.*)_en.js$/);
- let newUrl = match && match[1] + '.js';
- if (newUrl) {
- console.log(`REWRITING URL: ${req.url} -> ${newUrl}`);
- req.url = newUrl;
- }
- next();
- }
- ];
-
- // standalon back-end (proxyTarget) has higher priority, so it should be first
- if (devConfig.proxyTarget) {
- middlewares.push(
- proxy(['/api', '/onboarding-api', '/sdc1/feProxy/onboarding-api'], Object.assign({}, proxyConfigDefaults, {
- target: devConfig.proxyTarget,
- pathRewrite: {
- '/sdc1/feProxy/onboarding-api': '/onboarding-api'
- }
- }))
- );
- }
-
- // ATT environment (proxyATTTarget) has lower priority, so it should be second
- if (devConfig.proxyATTTarget) {
- middlewares.push(
- proxy(['/sdc1', '/onboarding-api', '/scripts', '/styles'], Object.assign({}, proxyConfigDefaults, {
- target: devConfig.proxyATTTarget,
- pathRewrite: {
- // Workaround for some weird proxy issue
- '/sdc1/feProxy/onboarding-api': '/sdc1/feProxy/onboarding-api',
- '/onboarding-api': '/sdc1/feProxy/onboarding-api'
- }
- }))
- );
- }
- server.use(middlewares);
-};
diff --git a/openecomp-ui/resources/scss/_modules.scss b/openecomp-ui/resources/scss/_modules.scss
index 317f90800f..405e91a61b 100644
--- a/openecomp-ui/resources/scss/_modules.scss
+++ b/openecomp-ui/resources/scss/_modules.scss
@@ -1,4 +1,5 @@
@import "modules/licenseModelOverview";
+@import "modules/licenseModelLimits";
@import "modules/licenseAgreement";
@import "modules/featureGroup";
@import "modules/entitlementPools";
diff --git a/openecomp-ui/resources/scss/bootstrap-cust/_modals.scss b/openecomp-ui/resources/scss/bootstrap-cust/_modals.scss
index 9301f1ed39..ad6b4f8aca 100644
--- a/openecomp-ui/resources/scss/bootstrap-cust/_modals.scss
+++ b/openecomp-ui/resources/scss/bootstrap-cust/_modals.scss
@@ -1,6 +1,7 @@
.modal-content {
.modal-header {
border-top: 3px solid $blue;
+ padding-left: 50px;
.modal-title {
@extend .heading-2;
}
diff --git a/openecomp-ui/resources/scss/common/_utils.scss b/openecomp-ui/resources/scss/common/_utils.scss
index dce623e15d..54f8b977a3 100644
--- a/openecomp-ui/resources/scss/common/_utils.scss
+++ b/openecomp-ui/resources/scss/common/_utils.scss
@@ -219,14 +219,10 @@ $browserPrefixes: webkit moz o ms;
width: $size;
height: $size;
background: $bgcolor;
- border: 3px solid $bgcolor;
- &:after {
- content: $content;
- position: relative;
- left: 9px;
- top: 9px;
- @extend .circle-icon-text;
- }
+ border: 3px solid $bgcolor;
+ display: flex;
+ align-items: center;
+ justify-content: center;
}
/**/
@@ -306,3 +302,12 @@ $browserPrefixes: webkit moz o ms;
@mixin border-shadow($xShadow: 0.545px, $yShadow: 0.839px, $blur: 4px, $spread: 0, $color: $light-gray, $opacity: 0.2) {
@include box-shadow($xShadow $yShadow $blur $spread rgba($color, $opacity));
}
+
+/* percent-plus-value */
+// @mixin
+// Calculate length property (e.g. width, margin) by adding a value (e.g. in pixels)
+// to a percentage of container height/width
+@mixin percent-plus-value($property, $value, $percent: 100%) {
+ $string: 'calc(' + $percent + ' + ' + $value + ')';
+ #{$property}: unquote($string);
+}
diff --git a/openecomp-ui/resources/scss/components/_datepicker.scss b/openecomp-ui/resources/scss/components/_datepicker.scss
index 593bb09d7d..d51a1b690e 100644
--- a/openecomp-ui/resources/scss/components/_datepicker.scss
+++ b/openecomp-ui/resources/scss/components/_datepicker.scss
@@ -1,5 +1,6 @@
.customized-date-picker {
margin-bottom: 24px;
+ display: flex;
.date-picker-label {
&.required {
&:before {
@@ -13,27 +14,38 @@
color: $dark-gray;
margin-bottom: 8px;
}
+ .react-datepicker__input-container {
+ flex: 1;
+ cursor: pointer;
+ }
.datepicker-custom-input {
display: flex;
justify-content: space-between;
- width: 243px;
+ align-items: center;
height: 30px;
border-radius: 2px;
color: $dark-gray;
border: 1px solid $light-gray;
- padding: 6px 12px;
+ padding: 6px 8px 6px 12px;
+ .clear-input {
+ margin-left: auto;
+ margin-right: 8px;
+ .svg-icon {
+ fill: transparent;
+ height: 8px;
+ width: 8px;
+ }
+ }
&:hover {
border-color: $gray;
.clear-input {
- &:before {
- cursor: pointer;
- content: 'x';
+ .svg-icon {
+ fill: initial;
}
}
}
.datepicker-text {
cursor: pointer;
- width: 170px;
@extend .body-1;
&.placeholder {
color: $light-gray;
@@ -43,9 +55,13 @@
.calendar-input {
fill: $light-gray;
}
+ .svg-icon-wrapper.calendar {
+ .svg-icon {
+ fill: $dark-gray;
+ width: 17px;
+ height: 17px;
+ }
+ }
}
-
-
-
}
diff --git a/openecomp-ui/resources/scss/components/_dualListBox.scss b/openecomp-ui/resources/scss/components/_dualListBox.scss
index 4a1a940c34..4353ab39e8 100644
--- a/openecomp-ui/resources/scss/components/_dualListBox.scss
+++ b/openecomp-ui/resources/scss/components/_dualListBox.scss
@@ -7,8 +7,7 @@
}
.dual-search-multi-select-section {
- $multi-select-box-width: 398px;
- width: $multi-select-box-width;
+ flex: 1;
.dual-text-box-search-title, .dual-list-box-multi-select-text {
@extend .body-1;
color: $dark-gray;
diff --git a/openecomp-ui/resources/scss/components/_notifications.scss b/openecomp-ui/resources/scss/components/_notifications.scss
index 7165e57ef9..5b10dee0ee 100644
--- a/openecomp-ui/resources/scss/components/_notifications.scss
+++ b/openecomp-ui/resources/scss/components/_notifications.scss
@@ -18,6 +18,12 @@
.modal-content .modal-header {
border-top: 3px solid $red;
}
+ }
+
+ &.negative {
+ .modal-content .modal-header {
+ border-top: 3px solid $red;
+ }
}
&.warning {
diff --git a/openecomp-ui/resources/scss/components/_selectActionTable.scss b/openecomp-ui/resources/scss/components/_selectActionTable.scss
index 4e42b6ce5b..79a5432ef1 100644
--- a/openecomp-ui/resources/scss/components/_selectActionTable.scss
+++ b/openecomp-ui/resources/scss/components/_selectActionTable.scss
@@ -72,6 +72,11 @@
fill: $green;
}
}
+ .svg-icon-wrapper.hideDelete {
+ .svg-icon {
+ fill: $white;
+ }
+ }
.select-action-table-row {
display: flex;
flex: 1;
@@ -80,6 +85,7 @@
&.has-error {
border-color: $red;
}
+
.select-action-table-cell {
flex: 1;
border-right: 1px solid;
@@ -127,10 +133,9 @@
border-bottom: 1px solid $blue;
overflow: auto;
.Select-menu {
- display: inline-block;
.Select-option {
- width: 100%;
- display: inline-block;
+ overflow: hidden;
+ text-overflow: ellipsis;
border-bottom: 1px solid $light-gray;
&:hover {
background-color: $blue;
diff --git a/openecomp-ui/resources/scss/components/_validationForm.scss b/openecomp-ui/resources/scss/components/_validationForm.scss
index 46269ad699..e4aac32b74 100644
--- a/openecomp-ui/resources/scss/components/_validationForm.scss
+++ b/openecomp-ui/resources/scss/components/_validationForm.scss
@@ -7,12 +7,10 @@ form {
.validation-radio-wrapper {
position: relative;
}
- .nav-tabs {
+ .sdc-tabs {
position: relative;
- .invalid-tab:not(.active) {
- a {
+ .invalid-tab:not(.sdc-tab-active) {
color: $red;
- }
}
}
.validation-error-message {
diff --git a/openecomp-ui/resources/scss/modules/_entitlementPools.scss b/openecomp-ui/resources/scss/modules/_entitlementPools.scss
index 0e0a72a387..ad0bb77e8d 100644
--- a/openecomp-ui/resources/scss/modules/_entitlementPools.scss
+++ b/openecomp-ui/resources/scss/modules/_entitlementPools.scss
@@ -1,6 +1,5 @@
-.entitlement-pools-list-editor {
-
+.entitlement-pools-list-editor {
.list-editor-view-list {
.list-editor-item-view {
min-height: 110px;
@@ -8,13 +7,9 @@
}
.list-editor-item-view-field {
- .entitlement-pools-count, .entitlement-parameters, .contract-number, .type{
+ .entitlement-pools-count, .contract-number, .type{
color: $purple;
}
- .entitlement-parameters {
- @include ellipsis;
- margin-bottom: 2px;
- }
.entitlement-pools-count {
@extend .heading-1;
margin-top: -10px;
@@ -25,22 +20,29 @@
}
.entitlement-pools-modal {
- .validation-form-content {
- padding: 50px;
- }
.modal-body {
padding: 0;
}
+ .sdc-tab-content {
+ margin: 0;
+ }
.entitlement-pools-form {
- .tab-content {
- padding: 50px;
- }
.threshold-section {
display: flex;
justify-content: space-between;
.validation-input-wrapper {
flex: 0 0 46%;
}
+ }
+ .date-section {
+ display: flex;
+ justify-content: space-between;
+ .validation-input-wrapper {
+ flex: 0 0 46%;
+ }
+ }
+ .validation-form-content {
+ padding: 20px 50px;
}
}
.validation-buttons {
diff --git a/openecomp-ui/resources/scss/modules/_featureGroup.scss b/openecomp-ui/resources/scss/modules/_featureGroup.scss
index 8c45d8ec58..9d395f98c8 100644
--- a/openecomp-ui/resources/scss/modules/_featureGroup.scss
+++ b/openecomp-ui/resources/scss/modules/_featureGroup.scss
@@ -32,6 +32,14 @@
margin-top: 55px;
color: $dark-gray;
}
+ .validation-form-content {
+ padding: 0;
+ }
+
+ .nav.nav-tabs {
+ padding-left: 50px;
+ }
+
.tab-content {
padding: 50px;
.field-section {
diff --git a/openecomp-ui/resources/scss/modules/_licenseKeyGroup.scss b/openecomp-ui/resources/scss/modules/_licenseKeyGroup.scss
index 5de757bf64..d072849c08 100644
--- a/openecomp-ui/resources/scss/modules/_licenseKeyGroup.scss
+++ b/openecomp-ui/resources/scss/modules/_licenseKeyGroup.scss
@@ -16,23 +16,3 @@
}
}
}
-
-.license-key-groups-modal {
- .modal-body {
- padding: 0;
- }
- .license-key-groups-form {
- .validation-form-content {
- padding: 50px;
- .field-section {
- @extend .body-2-semibold;
- margin-bottom: 23px;
- width: 400px;
- color: $black;
- }
- }
- .validation-buttons {
- padding: 20px 50px;
- }
- }
-}
diff --git a/openecomp-ui/resources/scss/modules/_licenseModel.scss b/openecomp-ui/resources/scss/modules/_licenseModel.scss
index 3d65be6274..fab091fe67 100644
--- a/openecomp-ui/resources/scss/modules/_licenseModel.scss
+++ b/openecomp-ui/resources/scss/modules/_licenseModel.scss
@@ -1,20 +1,53 @@
-.license-model-type-modal {
+.license-model-modal {
.modal-body {
padding: 0;
}
- .validation-form-content {
- padding: 50px;
- .field-section {
- @extend .body-2-semibold;
- margin-bottom: 23px;
- width: 400px;
- color: $black;
+ .modal-header {
+ border-bottom: none;
+ padding-bottom: 30px;
+ }
+ .modal-body {
+ padding: 0;
+ }
+ .sdc-tabs-list {
+ padding-left: 50px;
+ border-bottom: 1px solid $tlv-light-gray;
+ display: flex;
+ align-items: baseline;
+ }
+ .sdc-tab-content {
+ margin-top: 0;
+ }
+ .add-limit-button {
+ margin-left: auto;
+ margin-right: 50px;
+ padding-right: 0;
+ text-align: end;
+ }
+ .license-model-form {
+ .validation-form-content {
+ padding: 20px 50px;
+ }
+ .validation-buttons {
+ padding: 20px 50px;
}
- textarea {
- height: 107px;
+ &.license-agreement-form, &.feature-group-form {
+ .validation-form-content {
+ padding: 0;
+ }
+ .sdc-tab-content {
+ padding: 20px 50px;
+ }
+ }
+ }
+ .license-model-modal-buttons {
+ padding: 21px 50px;
+ display: flex;
+ justify-content: flex-end;
+ background-color: $tlv-gray;
+ margin-top: 2px;
+ .sdc-button {
+ margin-left: 20px;
}
- }
- .validation-buttons {
- padding: 20px 50px;
- }
+ }
}
diff --git a/openecomp-ui/resources/scss/modules/_licenseModelLimits.scss b/openecomp-ui/resources/scss/modules/_licenseModelLimits.scss
new file mode 100644
index 0000000000..32fd128f2e
--- /dev/null
+++ b/openecomp-ui/resources/scss/modules/_licenseModelLimits.scss
@@ -0,0 +1,121 @@
+.license-model-limits-view {
+ max-height: 490px;
+ overflow: auto;
+
+ .limit-editor-title {
+ padding: 10px 50px;
+ background-color: $blue;
+ color: $white;
+
+ }
+ .list-editor-view-add-title {
+ margin-right: 20px;
+ }
+
+ .no-limits-text {
+ padding-left: 50px;
+ }
+
+ .list-editor-view {
+ .list-editor-view-header {
+ border-bottom: none;
+ padding-top: 30px;
+ padding-bottom: 0;
+ }
+
+ .list-editor-view-list-scroller {
+ margin-top: 0;
+ margin-bottom: 30px;
+ }
+ .list-editor-view-list {
+ width: 100%;
+ .list-editor-item-view {
+ min-height: 50px;
+ height: 50px;
+ background-color: $tlv-light-gray;
+ border-color: transparent;
+ margin: 1px 0;
+ .list-editor-item-view-content {
+ padding-left: 0;
+ }
+ .svg-icon-wrapper.trashO {
+ margin-bottom: 0;
+ margin-right: 50px;
+ .svg-icon {
+ fill: $gray;
+ height: 16px;
+ width: 16px;
+ &:hover {
+ fill: $dark-gray;
+ }
+ }
+ }
+ &.selectable {
+ &:hover {
+ background-color: darken($tlv-light-gray, 4%);
+ cursor: pointer;
+ }
+ }
+ &:hover {
+ border-color: transparent;
+ cursor: default;
+ }
+ .list-editor-item-view-content {
+ .list-editor-item-view-field {
+ display: flex;
+ align-items: center;
+ white-space: nowrap;
+
+ &.limit-name {
+ .text.name {
+ @extend .body-1-semibold;
+ color: $blue;
+ text-transform: uppercase;
+ padding: 0px 10px;
+ }
+
+ border-right: 1px solid $light-gray;
+ margin-right: 22px;
+ flex: 0.4;
+ display: flex;
+ justify-content: center;
+ }
+
+ &.limit-description {
+ max-width: 300px;
+ margin-right: 22px;
+ }
+
+ &.limit-metric-details {
+ max-width: 300px;
+ }
+
+ .text.description, .text.name {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ }
+
+ }
+ }
+ }
+ }
+ .limit-editor{
+ .limit-editor-form {
+ .limit-editor-form-grid-section {
+ padding-bottom: 0;
+ }
+ .validation-form-content {
+ padding: 21px 45px;
+ }
+ .limit-editor-buttons {
+ display: flex;
+ justify-content: flex-end;
+ .sdc-button {
+ margin-left: 20px;
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/openecomp-ui/resources/scss/modules/_licenseModelOverview.scss b/openecomp-ui/resources/scss/modules/_licenseModelOverview.scss
index 5c74e82d83..1c133a1dce 100644
--- a/openecomp-ui/resources/scss/modules/_licenseModelOverview.scss
+++ b/openecomp-ui/resources/scss/modules/_licenseModelOverview.scss
@@ -1,3 +1,21 @@
+$list-indentation: 20px;
+$arrow-margin: 30px;
+$icon-margin: 30px;
+$arrow-element-width: 30px;
+$list-item-padding: 15px;
+
+@mixin overview-tile-shadow() {
+ @include box-shadow(0.5px 0.8px 4px 0 rgba(24, 24, 25, 0.05));
+}
+
+// @mixin vlm-list-item-inset($color) {
+// @include box-shadow(inset 6px 0 0 0 $color);
+// }
+
+$la-color: $dark-blue;
+$fg-color: $blue;
+$lkg-ep-color: $light-blue;
+
.license-model-overview {
.overview-top-section {
.overview-title{
@@ -20,60 +38,61 @@
.vendor-data-view {
@extend .flex-column;
background-color: $tlv-gray;
- padding: 20px 30px;
+ padding: 13px 30px;
border: 1px solid $tlv-light-gray;
- @include border-shadow();
+ @include overview-tile-shadow();
.vendor-title {
margin-top:5px;
}
.vendor-name {
@extend .heading-4-semibold;
text-transform: none;
- padding-bottom: 15px;
+ padding-bottom: 10px;
border-bottom: 1px solid $tlv-light-gray;
}
- .vendor-description {
+ .vendor-description, .vendor-description-readonly {
@extend .flex;
@extend .body-1;
justify-content: space-between;
- margin-top: 10px;
overflow: hidden;
+ position: relative;
+ flex: initial;
+ }
+
+ &:not(.read-only) .vendor-description {
border: 1px solid transparent;
- position: relative;
- left: -6px;
- width: 101%;
+ padding: 2px 0 2px 6px;
+ margin-top: 10px;
+ $hover-padding-right: 16px;
+ @include percent-plus-value($property: width, $percent: 100%, $value: -$hover-padding-right); // compensate for padding added on hover
&:hover {
- border: 1px solid $tlv-light-gray;
- background-position: 99% 12%;
- background-size: 15px;
- padding-right: 20px;
+ padding-right: $hover-padding-right;
+ width: 100%;
+ border: 1px solid $light-gray;
+ cursor: pointer;
+
+ background-position: calc(100% - 4px) 4px;
+ background-size: 14px;
background-image: url($pencil-icon);
background-repeat: no-repeat;
- cursor: pointer;
- }
- &.read-only {
- border: none;
+ background-color: white;
+
+ .description-data:after {
+ background: white;
+ }
}
- .description-data {
- @include multiline-ellipsis($lineCount: 3, $bgColor: $tlv-gray);
- }
}
.vendor-description-readonly {
- @extend .flex;
- @extend .body-1;
- justify-content: space-between;
- margin-top: 10px;
- overflow: hidden;
- border: none;
- height: 49px;
- margin-bottom: 15px;
- padding: 6px;
- position: relative;
- left:-6px;
+ margin-top: 16px;
}
+ .description-data {
+ @include multiline-ellipsis($lineCount: 3, $bgColor: $tlv-gray);
+ flex: initial;
+ }
+
.vendor-description-edit {
@extend .flex;
flex-direction: column;
@@ -84,6 +103,7 @@
width: 101%;
textarea {
padding-left: 6px;
+ resize: vertical;
}
.buttons-row {
@extend .flex;
@@ -133,12 +153,12 @@
margin-left: 20px;
justify-content: space-between;
border: 1px solid $tlv-light-gray;
- @include border-shadow();
+ @include overview-tile-shadow();
background-color: $tlv-gray;
.summary-count-item {
@extend .flex;
- @extend .heading-5-semibold;
- padding-top: 5px;
+ @extend .heading-5-semibold;
+ align-items: center;
padding-left: 45px;
padding-right: 45px;
border-bottom: 1px solid $tlv-light-gray;
@@ -184,9 +204,10 @@
}
}
}
- .vlm-list-tab-panel
- {
- @extend .flex;
+ .vlm-list-tab-panel {
+
+ @extend .flex;
+ margin-bottom: 7px;
.section-title {
flex: 1;
}
@@ -236,81 +257,33 @@
}
.vlm-list-view {
.vlm-list {
- .vlm-list-item {
- @include border-shadow();
- .list-item-icon-col {
- display: flex;
- flex-direction: column;
- justify-content: center;
- margin-left: 5px;
- }
- &.vlm-list-item-la {
- margin-left: 0;
- .list-item-icon-col {
- padding-left: 22px;
+ .vlm-list-item.orphan-list-item {
+ @include overview-tile-shadow();
+ margin-left: 0;
+
+ .vlm-list-item-title {
- }
- .la-icon {
- background-color: $gray;
- border-color: $gray;
- }
- .list-item-section {
- &:first-child {
- background-color: gray;
- }
- }
- }
- &.vlm-list-item-fg {
- cursor: default;
- margin-left: 0;
- border-left: 10px solid $gray;
- .list-item-arrow-col {
- margin-left: 0px;
- }
- .list-item-icon-col {
- padding-left: 22px;
- }
- .fg-icon {
- background-color: $gray;
- border-color: $gray;
- }
- }
- &.vlm-list-item-ep {
- margin-left: 0;
- border-left: 10px solid $gray;
- .list-item-icon-col {
- padding-left: 22px;
- }
- .ep-icon {
- background-color: $gray;
- border-color: $gray;
- }
- .list-item-section {
- &:first-child {
- display: flex;
- color: $white;
- min-width: 34px;
- }
- }
- }
- &.vlm-list-item-lkg {
- margin-left: 0;
- border-left: 10px solid $gray;
- .list-item-icon-col {
- padding-left: 22px;
- }
- .lkg-icon {
- background-color: $gray;
- border-color: $gray;
- }
- .list-item-section {
- &:first-child {
- display: flex;
- color: $white;
- min-width: 34px;
- }
- }
- }
+ .item-name {
+ color: $dark-gray;
+ }
+ }
+ .list-item-icon-col {
+ .overview-list-icon {
+ background-color: $gray;
+ border-color: $gray;
+ }
+ }
+ .list-item-section {
+ &:first-child {
+ display: flex;
+ color: $white;
+ min-width: $arrow-element-width;
+ }
+ &.list-item-icon-col {
+ margin-left: 65px;
+ margin-right: 65px - $list-item-padding;
+ }
+ }
}
}
}
@@ -328,18 +301,32 @@
@extend .flex;
border: 1px solid $tlv-light-gray;
margin-bottom: 0px;
- cursor: pointer;
- .list-item-icon-col {
- display: flex;
- flex-direction: column;
- justify-content: center;
-
- }
+ .clickable {
+ cursor: pointer;
+ }
+
.list-item-section {
- padding: 10px;
+ .count-value {
+ @extend .body-3;
+ }
+ &.list-item-icon-col {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ padding: 0;
+ margin-right: 40px - $list-item-padding;
+ margin-left: $icon-margin;
+ .overview-list-icon {
+ @extend .body-2;
+ }
+ }
+ padding: 15px;
+ &.list-item-arrow-col {
+ padding: 0;
+ }
.children-count {
@extend .body-1;
- line-height: 20px;
color: $gray;
padding-left: 5px;
.count-value {
@@ -347,9 +334,18 @@
}
}
.additional-data {
- padding-left: 50px;
+ padding-left: 60px;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ *:last-child {
+ margin-top: 20px;
+ }
+ *:only-child {
+ margin-top: 0;
+ }
.additional-data-name {
- @extend .body-1-semibold;
+ @extend .body-2-semibold;
}
}
.additional-data-col-border {
@@ -359,128 +355,140 @@
}
}
.list-item-additional-data-col {
- @extend .body-1;
+ @extend .body-2;
@extend .flex;
- align-items: center;
- flex: 0.8;
+ align-items: stretch;
+ flex: 0.8;
+ margin-left: 30px;
+ padding-top: 17px;
+ padding-bottom: 11px;
}
.arrow-icon {
- align-self: center;
+ align-self: center;
+
}
.vlm-item-info {
flex: 1;
}
.vlm-list-item-title {
- @extend .flex;
+ @extend .flex;
+ align-items: baseline;
.item-name {
@extend .heading-5-semibold;
flex: 0 1 auto;
- margin-bottom: 4px;
+ margin-bottom: 4px;
+ text-transform: uppercase;
}
}
.vlm-list-item-description {
@extend .body-1;
- overflow: hidden;
+ @include multiline-ellipsis($lineCount: 3, $bgColor: $tlv-gray);
max-height: 38px;
}
&.vlm-list-item-la {
margin-top: 10px;
- border-left: 10px solid $dark-blue;
.la-icon {
- @include create-circle($circle-icon-size,$dark-blue,'LA');
+ @include create-circle($circle-icon-size,$la-color,'LA');
color: $white;
- }
+ }
+ .vlm-list-item-title {
+ .item-name {
+ color: $la-color;
+ }
+ }
.list-item-section {
&:first-child {
display: flex;
- color: $dark-blue;
- min-width: 34px;
+ color: $la-color;
+ min-width: $arrow-element-width;
}
}
.list-item-arrow-col {
flex: 0.01;
- margin-left: 14px;
- }
- .list-item-icon-col {
- padding-left: 14px;
- padding-right: 30px;
- align-items: center;
+ margin-left: $arrow-margin;
+ justify-content: center;
}
-
}
&.vlm-list-item-fg {
- border-left: 10px solid $blue;
- margin-left: 20px;
- margin-top: 10px;
+ margin-left: $list-indentation;
+ margin-top: 10px;
+ .fg-pipeline-separator {
+ color: $dark-gray;
+ padding: 0 5px;
+ }
+ .list-item-icon-col {
+ margin-left: 29px;
+ }
.fg-icon {
- @include create-circle($circle-icon-size,$blue,'FG');
+ @include create-circle($circle-icon-size,$fg-color,'FG');
color: $white;
- }
+ }
+
+ .vlm-list-item-title {
+ .item-name {
+ color: $fg-color;
+ }
+ }
.list-item-section {
&:first-child {
display: flex;
- color: $blue;
- min-width: 34px;
+ color: $fg-color;
+ min-width: $arrow-element-width;
}
}
.list-item-arrow-col {
flex: 0.01;
- margin-left: 26px;
- }
- .list-item-icon-col {
- padding-left: 22px;
- padding-right: 30px;
- align-items: center;
+ margin-left: $arrow-margin - $list-indentation;
+ padding-left: $list-indentation;
}
}
&.vlm-list-item-ep {
- margin-left: 40px;
+ margin-left: $list-indentation * 2;
margin-top: 10px;
- border-left: 10px solid $light-blue;
cursor: default;
.ep-icon {
- @include create-circle($circle-icon-size,$light-blue,'EP');
+ @include create-circle($circle-icon-size,$lkg-ep-color,'EP');
color: $white;
- }
- .list-item-icon-col {
- padding-left: 72px;
- padding-right: 30px;
- align-items: center;
- }
+ }
+ .vlm-list-item-title {
+ .item-name {
+ color: $lkg-ep-color;
+ }
+ }
.list-item-section {
&:first-child {
display: none;
- }
- }
- .list-item-additional-data-col {
- margin-right: 20px;
+ }
+ &.list-item-icon-col {
+ margin-left: 52px;
+ }
}
+
}
&.vlm-list-item-lkg {
margin-top: 10px;
- margin-left: 40px;
- border-left: 10px solid $light-blue;
+ margin-left: $list-indentation * 2;
cursor: default;
.lkg-icon {
- @include create-circle($circle-icon-size,$light-blue,'KG');
+ @include create-circle($circle-icon-size,$lkg-ep-color,'KG');
color: $white;
- }
- .list-item-icon-col {
- padding-left: 72px;
- padding-right: 30px;
- align-items: center;
- }
+ }
+ .vlm-list-item-title {
+ .item-name {
+ color: $lkg-ep-color;
+ }
+ }
.list-item-section {
&:first-child {
display: none;
- }
+ }
+ &.list-item-icon-col {
+ margin-left: 52px;
+ }
}
- .list-item-additional-data-col {
- margin-right: 20px;
- }
}
}
diff --git a/openecomp-ui/resources/scss/modules/onboardingCatalog/_catalogTile.scss b/openecomp-ui/resources/scss/modules/onboardingCatalog/_catalogTile.scss
index 07f86aba2a..87a852f755 100644
--- a/openecomp-ui/resources/scss/modules/onboardingCatalog/_catalogTile.scss
+++ b/openecomp-ui/resources/scss/modules/onboardingCatalog/_catalogTile.scss
@@ -48,6 +48,9 @@
align-self: baseline;
color: $gray;
line-height: 10px;
+ &:first-letter {
+ text-transform: capitalize;
+ }
@include ellipsis(auto, inline-block, 178px);
}
@@ -56,7 +59,10 @@
@extend .heading-5-semibold;
color: $black;
@include ellipsis(auto, inline-block, 175px);
- line-height: inherit;
+ line-height: inherit;
+ &:first-letter {
+ text-transform: capitalize;
+ }
}
}
.catalog-tile-icon {
diff --git a/openecomp-ui/resources/scss/modules/onboardingCatalog/_vendorTile.scss b/openecomp-ui/resources/scss/modules/onboardingCatalog/_vendorTile.scss
index 5972bb2d67..d490fd6e1c 100644
--- a/openecomp-ui/resources/scss/modules/onboardingCatalog/_vendorTile.scss
+++ b/openecomp-ui/resources/scss/modules/onboardingCatalog/_vendorTile.scss
@@ -24,7 +24,10 @@
.catalog-tile-top {
.catalog-tile-item-name {
margin-top: 21px;
- line-height: inherit;
+ line-height: inherit;
+ &:first-letter {
+ text-transform: capitalize;
+ }
}
.catalog-tile-vsp-count {
@extend .body-3-semibold;
diff --git a/openecomp-ui/resources/scss/onboarding.scss b/openecomp-ui/resources/scss/onboarding.scss
index d7d4586354..b49a7cb423 100644
--- a/openecomp-ui/resources/scss/onboarding.scss
+++ b/openecomp-ui/resources/scss/onboarding.scss
@@ -12,53 +12,73 @@
div[data-reactroot].customized-date-picker-calendar {
@import "common/variables";
@import "common/typography";
- border-radius: 2px;
border-color: $light-gray;
margin-top: -8px;
+ color: $black;
.react-datepicker__triangle {
margin-top: 0px;
}
.react-datepicker__navigation--previous {
- border: none;
- width: 15px;
- height: 15px;
+ border: none;
+ width: 12px;
+ height: 12px;
margin-top: 2px;
- content: url(../images/angle-left.svg);
+ content: url(../images/angle-left.svg);
}
.react-datepicker__navigation--next {
- border: none;
- width: 15px;
- height: 15px;
- margin-top: 2px;
- content: url(../images/angle-right.svg);
+ border: none;
+ width: 12px;
+ height: 12px;
+ margin-top: 2px;
+ content: url(../images/angle-right.svg);
}
- .react-datepicker__month-container {
+ .react-datepicker__month-container {
.react-datepicker__header {
background-color: $background-gray;
border-bottom: none;
.react-datepicker__current-month {
- @extend .heading-5;
+ @extend .body-1-semibold;
background-color: $background-gray;
- margin-bottom: 10px;
+ margin-bottom: 10px;
}
.react-datepicker__day-names {
- @extend .heading-5;
+ @extend .body-1;
background-color: $white;
}
}
- .react-datepicker__day--selected {
- @extend .heading-5;
- border-radius: 20px;
+ .react-datepicker__day--selected, .react-datepicker__day--keyboard-selected {
+ @extend .body-1;
background-color: $blue;
- &:hover {
- background-color: $dark-blue;
- }
+ color: $white;
}
.react-datepicker__day {
- @extend .heading-5;
- &:hover {
- border-radius: 20px;
- }
+ border-radius: 0px;
+ margin: 0;
+ flex: 1;
+ @extend .body-1;
+ }
+
+ .react-datepicker__day--in-range, .react-datepicker__day--in-selecting-range {
+ background-color: $tlv-hover;
+ color: $black;
+ &.react-datepicker__day--selected, &.react-datepicker__day--keyboard-selected, &.react-datepicker__day--range-start, &.react-datepicker__day--range-end {
+ background-color: $blue;
+ color: $white;
+ }
+ &.react-datepicker__day--selecting-range-start, &.react-datepicker__day--selecting-range-end {
+ background-color: lighten($blue, 40%);
+ color: $black;
+ }
+ &.react-datepicker__day--selecting-range-start.react-datepicker__day--range-start,
+ &.react-datepicker__day--selecting-range-end.react-datepicker__day--range-end,
+ &.react-datepicker__day--selecting-range-start.react-datepicker__day--keyboard-selected {
+ background-color: $blue;
+ color: $white;
+ }
+ }
+
+ .react-datepicker__week {
+ display: flex;
}
}
}
@@ -69,7 +89,7 @@ div[data-reactroot].tooltip {
@import "common/typography";
&.in {
- opacity: 1;
+ opacity: 1;
}
&.validation-error-message {
&.bottom {
@@ -94,28 +114,33 @@ div[data-reactroot].tooltip {
}
}
&.bottom {
- .tooltip-arrow {
- border-bottom-color: $dark-gray !important;
- }
+ .tooltip-arrow {
+ border-bottom-color: $dark-gray !important;
+ }
}
&.top {
- .tooltip-arrow {
- border-top-color: $dark-gray !important;
- }
+ .tooltip-arrow {
+ border-top-color: $dark-gray !important;
+ }
}
.tooltip-inner {
- max-width: 100%;
- background-color: $dark-gray;
+ @extend .body-1;
+ max-width: 100%;
+ background-color: $dark-gray;
+ padding: 6px 9px;
+ &:first-letter {
+ text-transform: capitalize;
+ }
}
// activity log tooltip
&.activity-log-message-tooltip {
- @include base-font-regular;
- font-size: $body-font-2;
- .message-block {
- text-align: left;
- padding: 3px 12px;
- }
+ @include base-font-regular;
+ font-size: $body-font-2;
+ .message-block {
+ text-align: left;
+ padding: 3px 12px;
+ }
}
//dependency table error tooltip
&.select-action-table-error-tooltip{
@@ -136,4 +161,11 @@ div[data-reactroot].tooltip {
font-size: $body-font-2;
}
}
+
+ // for read-only mode, vendor description in VLM overview
+ &.vendor-description-tooltip {
+ .tooltip-inner {
+ max-width: 600px;
+ }
+ }
}
diff --git a/openecomp-ui/runLocalFE.cmd b/openecomp-ui/runLocalFE.cmd
deleted file mode 100644
index ee718f2a0b..0000000000
--- a/openecomp-ui/runLocalFE.cmd
+++ /dev/null
@@ -1,38 +0,0 @@
-@REM /*!
-@REM * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
-@REM *
-@REM * Licensed under the Apache License, Version 2.0 (the "License");
-@REM * you may not use this file except in compliance with the License.
-@REM * You may obtain a copy of the License at
-@REM *
-@REM * http://www.apache.org/licenses/LICENSE-2.0
-@REM *
-@REM * Unless required by applicable law or agreed to in writing, software
-@REM * distributed under the License is distributed on an "AS IS" BASIS,
-@REM * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
-@REM * or implied. See the License for the specific language governing
-@REM * permissions and limitations under the License.
-@REM */
-
-@echo off
-
-SETLOCAL
-
-set uiDir=%cd%
-set currentDir=%cd%
-if not ("%1" == "") set uiDir=%1
-
-echo check npm version:
-call npm -version
-if errorlevel 1 (
- echo install node with npm from https://nodejs.org/en/download/
- goto done
-)
-echo npm is installed
-echo one more check...
-call npm list prompt
-if errorlevel 1 (
- npm install prompt
-)
-echo ready to run
-call node runLocalFE.js
diff --git a/openecomp-ui/runLocalFE.js b/openecomp-ui/runLocalFE.js
deleted file mode 100644
index 1205aa48f9..0000000000
--- a/openecomp-ui/runLocalFE.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/*!
- * 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.
- */
-
-var exec = require('child_process');
-var prompt = require('prompt');
-var fs = require('fs');
-
-
-function runNpm(target, dir) {
- console.log('\n---> npm ' + target);
- let options = {stdio:[0,1,2]};
- if (dir) options.cwd = dir;
- exec.execSync("npm " + target,options);
-}
-
-function npmInstallAll() {
- setNpmconfig();
- if (!fs.existsSync('../dox-sequence-diagram-ui/node_modules')) {
- console.log('--> first time installing dox-sequence-diagram-ui');
- runNpm('install', '../dox-sequence-diagram-ui');
- };
- runNpm('install');
- // just to make sure restful js is installed properly
- runNpm('install jquery', 'node_modules/restful-js');
-}
-
-function getDevConfig() {
- var content=fs.readFileSync('./devConfig.json');
- var data=JSON.parse(content);
- console.log('Current ATT server is set to: ' + data.proxyATTTarget);
- if (!data.proxyTarget) {
- console.log('Current onboarding server defaults to the ATT server');
- } else {
- console.log('Current onboarding server set to: ' + data.proxyTarget);
- }
- return data;
-}
-
-function setNpmconfig() {
- exec.execSync("npm config set proxy http://genproxy.amdocs.com:8080");
- exec.execSync("npm config set https_proxy http://genproxy.amdocs.com:8080");
-}
-
-// getting the run details before starting to work
-prompt.start();
-prompt.get([{
- name:'runType',
- type:'number',
- default:1,
- description: 'Choose run: 1-test and build, 2- run frontend server '
- }], function (err, result) {
- if (result.runType === 2) {
- console.log('--> Reading the configuration for the local server');
- if (!fs.existsSync('./devConfig.json')) {
- console.log('First time - setting up the devConfig.json file');
- fs.writeFileSync('./devConfig.json', fs.readFileSync('./devConfig.defaults.json'));
- }
- let data = getDevConfig();
- let attProxyField = {
- name:'attProxyTarget',
- description:'ATT server'
- };
- let proxyField = {
- name:'proxyTarget',
- description:'onboarding server, \'null\' to reset'
- };
- if (data.proxyATTTarget) attProxyField.default = data.proxyATTTarget;
- if (data.proxyTarget) proxyField.default = data.proxyTarget;
- prompt.get([ attProxyField, proxyField], function (err,result) {
- data.proxyATTTarget = result.attProxyTarget;
- if(result.proxyTarget) {
- if (result.proxyTarget === 'null') {
- if (data.proxyTarget) delete data.proxyTarget;
- } else {
- data.proxyTarget = result.proxyTarget;
- }
- }
- fs.writeFileSync('./devConfig.json', JSON.stringify(data, null, 2));
- getDevConfig();
- console.log('FE server will be answering on: http://localhost:9000/sdc1/proxy-designer1#/onboardVendor');
- npmInstallAll();
- runNpm("start");
- }
- );
- } else {
- npmInstallAll();
- runNpm("run build");
- runNpm("run test");
- }
-});
-
diff --git a/openecomp-ui/src/index.html b/openecomp-ui/src/index.html
index d4fab4dcb2..6a9265c984 100644
--- a/openecomp-ui/src/index.html
+++ b/openecomp-ui/src/index.html
@@ -11,4 +11,4 @@
</body>
</html>
-npm
+
diff --git a/openecomp-ui/src/nfvo-components/datepicker/Datepicker.jsx b/openecomp-ui/src/nfvo-components/datepicker/Datepicker.jsx
index cd39376bda..f4673c1c93 100644
--- a/openecomp-ui/src/nfvo-components/datepicker/Datepicker.jsx
+++ b/openecomp-ui/src/nfvo-components/datepicker/Datepicker.jsx
@@ -17,10 +17,10 @@ class CustomInput extends React.Component {
const text = date ? date : placeholderText;
const textStyle = date ? '' : 'placeholder';
return (
- <div ref={inputRef} className='datepicker-custom-input'>
- <div onClick={onClick} className={`datepicker-text ${textStyle}`}>{text}</div>
- <div onClick={onClear} className='clear-input'/>
- <SVGIcon onClick={onClick} name='calendar'/>
+ <div onClick={onClick} ref={inputRef} className='datepicker-custom-input'>
+ <div className={`datepicker-text ${textStyle}`}>{text}</div>
+ {date && <SVGIcon onClick={e => {e.stopPropagation(); onClear();}} name='close' className='clear-input'/>}
+ <SVGIcon name='calendar'/>
</div>
);
}
diff --git a/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx b/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx
index 6e54254eb0..9b11d27c2b 100644
--- a/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx
+++ b/openecomp-ui/src/nfvo-components/input/validation/InputOptions.jsx
@@ -64,7 +64,8 @@ class InputOptions extends React.Component {
const dataTestId = this.props['data-test-id'] ? {'data-test-id': this.props['data-test-id']} : {};
let currentMultiSelectedEnum = [];
let currentSelectedEnum = '';
- let {otherInputDisabled} = this.state;
+ let otherInputDisabled = (isMultiSelect && (multiSelectedEnum === undefined || multiSelectedEnum.length === 0 || multiSelectedEnum[0] !== other.OTHER))
+ || (!isMultiSelect && (selectedEnum === undefined || selectedEnum !== other.OTHER));
if (isMultiSelect) {
currentMultiSelectedEnum = multiSelectedEnum;
if(!otherInputDisabled) {
diff --git a/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx b/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx
index 95144b1468..6f33536b04 100644
--- a/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx
+++ b/openecomp-ui/src/nfvo-components/input/validation/Tabs.jsx
@@ -15,7 +15,7 @@
*/
import React from 'react';
import ReactDOM from 'react-dom';
-import {default as BTabs} from 'react-bootstrap/lib/Tabs.js';
+import {default as SDCTabs} from 'sdc-ui/lib/react/Tabs.js';
import Overlay from 'react-bootstrap/lib/Overlay.js';
import Tooltip from 'react-bootstrap/lib/Tooltip.js';
@@ -33,15 +33,15 @@ class Tabs extends React.Component {
return React.cloneElement(
element,
{
- key: element.props.eventKey,
- tabClassName: invalidTabs.indexOf(element.props.eventKey) > -1 ? 'invalid-tab' : 'valid-tab'
+ key: element.props.tabId,
+ className: invalidTabs.indexOf(element.props.tabId) > -1 ? 'invalid-tab' : 'valid-tab'
}
);
}
showTabsError() {
const {invalidTabs} = this.props;
- const showError = ((invalidTabs.length === 1 && invalidTabs[0] !== this.props.activeKey) || (invalidTabs.length > 1));
+ const showError = ((invalidTabs.length === 1 && invalidTabs[0] !== this.props.activeTab) || (invalidTabs.length > 1));
return showError;
}
@@ -50,21 +50,20 @@ class Tabs extends React.Component {
let {invalidTabs, ...tabProps} = this.props;
return (
<div>
- <BTabs {...tabProps} ref='tabsList' id='tabsList' >
+ <SDCTabs {...tabProps} ref='tabsList' id='tabsList' >
{this.props.children.map(element => this.cloneTab(element))}
- </BTabs>
+ </SDCTabs>
<Overlay
animation={false}
show={this.showTabsError()}
placement='bottom'
- containerPadding={50}
target={() => {
- let target = ReactDOM.findDOMNode(this.refs.tabsList).querySelector('ul > li.invalid-tab:not(.active):nth-of-type(n)');
+ let target = ReactDOM.findDOMNode(this.refs.tabsList).querySelector('ul > li.invalid-tab:not(.sdc-tab-active):nth-of-type(n)');
return target && target.offsetParent ? target : undefined;
}
}
container={() => {
- let target = ReactDOM.findDOMNode(this.refs.tabsList).querySelector('ul > li.invalid-tab:not(.active):nth-of-type(n)');
+ let target = ReactDOM.findDOMNode(this.refs.tabsList).querySelector('ul > li.invalid-tab:not(.sdc-tab-active):nth-of-type(n)');
return target && target.offsetParent ? target.offsetParent : this;
}}>
<Tooltip
diff --git a/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx b/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx
index 8d7c63f567..bed304b756 100644
--- a/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx
+++ b/openecomp-ui/src/nfvo-components/listEditor/ListEditorItemView.jsx
@@ -39,7 +39,7 @@ class ListEditorItem extends React.Component {
</div>
{(onEdit || onDelete) && <div className='list-editor-item-view-controller'>
{onEdit && <SVGIcon name='sliders' onClick={() => this.onClickedItem(onEdit)}/>}
- {onDelete && isAbilityToDelete && <SVGIcon name='trashO' onClick={() => this.onClickedItem(onDelete)}/>}
+ {onDelete && isAbilityToDelete && <SVGIcon name='trashO' data-test-id='delete-list-item' onClick={() => this.onClickedItem(onDelete)}/>}
</div>}
</div>
);
diff --git a/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js b/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js
index 9af142433c..c2548e4fb4 100644
--- a/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js
+++ b/openecomp-ui/src/nfvo-components/panel/versionController/VersionControllerConstants.js
@@ -33,7 +33,7 @@ export const statusEnum = keyMirror({
export const statusBarTextMap = keyMirror({
'Locked': 'Checked Out',
- 'LockedByUser': '',
+ 'LockedByUser': 'Locked',
'Available': 'Checked In',
'Final': 'Submitted',
'READ ONLY': 'Locked'
diff --git a/openecomp-ui/src/nfvo-components/table/SelectActionTable.jsx b/openecomp-ui/src/nfvo-components/table/SelectActionTable.jsx
index 6c04ad74fd..12e9a06623 100644
--- a/openecomp-ui/src/nfvo-components/table/SelectActionTable.jsx
+++ b/openecomp-ui/src/nfvo-components/table/SelectActionTable.jsx
@@ -16,7 +16,7 @@ export default class SelectActionTable extends React.Component {
<div className='select-action-table'>
<div className='select-action-table-headers'>
{columns.map(column => <div key={uuid.create()} className='select-action-table-header'>{i18n(column)}</div>)}
- {Array(numOfIcons).fill().map(() => <SVGIcon name='trashO' className='dummy-icon' />)}
+ {Array(numOfIcons).fill().map((e, i) => <SVGIcon name='trashO' key={i} className='dummy-icon' />)}
</div>
<div className='select-action-table-body'>
{children}
diff --git a/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx b/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx
index a711b42918..7df7d532e8 100644
--- a/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx
+++ b/openecomp-ui/src/nfvo-components/table/SelectActionTableRow.jsx
@@ -27,12 +27,12 @@ function renderErrorOrCheck({hasError, overlayMsg}) {
return <SVGIcon name='checkCircle'/>;
}
-const SelectActionTableRow = ({children, onDelete, hasError, hasErrorIndication, overlayMsg}) => (
+const SelectActionTableRow = ({children, onDelete, hasError, hasErrorIndication, overlayMsg, showDelete}) => (
<div className='select-action-table-row-wrapper'>
<div className={`select-action-table-row ${hasError ? 'has-error' : ''}`}>
{children}
</div>
- {onDelete && <SVGIcon name='trashO' data-test-id='select-action-table-delete' onClick={onDelete} />}
+ {onDelete && <SVGIcon name='trashO' iconClassName={(showDelete) ? '' : 'hideDelete'} data-test-id='select-action-table-delete' onClick={(showDelete) ? onDelete : null} />}
{hasErrorIndication && renderErrorOrCheck({hasError, overlayMsg})}
</div>
);
diff --git a/openecomp-ui/src/nfvo-utils/Validator.js b/openecomp-ui/src/nfvo-utils/Validator.js
index 8fcf24a714..1df82a2ada 100644
--- a/openecomp-ui/src/nfvo-utils/Validator.js
+++ b/openecomp-ui/src/nfvo-utils/Validator.js
@@ -20,7 +20,9 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
class Validator {
static get globalValidationFunctions() {
return {
- required: value => value !== '',
+ required: value => {
+ return typeof value === 'string' ? value.replace(/\s+/g, '') !== '' : value !== '';
+ },
requiredChooseOption: value => value !== '',
maxLength: (value, length) => ValidatorJS.isLength(value, {max: length}),
minLength: (value, length) => ValidatorJS.isLength(value, {min: length}),
@@ -107,6 +109,7 @@ class Validator {
}
static isItemNameAlreadyExistsInList({itemId, itemName, list}) {
+ itemName = itemName.toLowerCase();
return list[itemName] && list[itemName] !== itemId;
}
}
diff --git a/openecomp-ui/src/nfvo-utils/getValue.js b/openecomp-ui/src/nfvo-utils/getValue.js
new file mode 100644
index 0000000000..e6871c094d
--- /dev/null
+++ b/openecomp-ui/src/nfvo-utils/getValue.js
@@ -0,0 +1,32 @@
+/*!
+ * 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 {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+
+function getValueFromObject(element) {
+ return element.choices && element.choices.length > 0 && element.choices[0] !== '' && element.choices[0] !== optionInputOther.OTHER ||
+ element.other && element.choices[0] === optionInputOther.OTHER ?
+ element : undefined;
+}
+
+function getValueFromVariable(variable) {
+ return variable ? variable : undefined;
+}
+
+ let getValue = element => {
+ return typeof element === 'object' ? getValueFromObject(element) : getValueFromVariable(element);
+ };
+
+ export default getValue; \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js b/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js
index 0bbb5e63be..2276984f7a 100644
--- a/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js
+++ b/openecomp-ui/src/sdc-app/common/reducers/PlainDataReducer.js
@@ -16,6 +16,7 @@
import {actionTypes} from './PlainDataReducerConstants.js';
import Validator from 'nfvo-utils/Validator.js';
import forOwn from 'lodash/forOwn.js';
+import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
function updateDataAndValidateReducer(state = {}, action) {
let genericFieldInfoCopy;
@@ -46,6 +47,12 @@ function updateDataAndValidateReducer(state = {}, action) {
forOwn(state.genericFieldInfo,(value, key) => {
let val = state.data && state.data[key] ? state.data[key] : '';
let result = Validator.validate(key, val, state.genericFieldInfo[key].validations, state, {});
+ if(val.choice !== undefined) {
+ result = Validator.validate(key, val.choice, state.genericFieldInfo[key].validations, state, {});
+ }
+ if(val.choice !== undefined && val.choice === optionInputOther.OTHER) {
+ result = Validator.validate(key, val.other, state.genericFieldInfo[key].validations, state, {});
+ }
genericFieldInfoCopy[key] = {...genericFieldInfoCopy[key], isValid: result.isValid, errorText: result.errorText};
if (!result.isValid) {
formReady = false;
diff --git a/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
index 2b59361eef..dad930127b 100644
--- a/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
@@ -31,8 +31,7 @@ import OnboardActionHelper from './onboard/OnboardActionHelper.js';
import SoftwareProductComponentsMonitoringAction from './softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringActionHelper.js';
import {actionTypes, enums} from './OnboardingConstants.js';
import SoftwareProductComponentsImageActionHelper from './softwareProduct/components/images/SoftwareProductComponentsImageActionHelper.js';
-import {navigationItems as SoftwareProductNavigationItems, actionTypes as SoftwareProductActionTypes,
- onboardingMethod as onboardingMethodTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
+import {navigationItems as SoftwareProductNavigationItems, actionTypes as SoftwareProductActionTypes} from 'sdc-app/onboarding/softwareProduct/SoftwareProductConstants.js';
import ActivityLogActionHelper from 'sdc-app/common/activity-log/ActivityLogActionHelper.js';
import licenseModelOverviewActionHelper from 'sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js';
import store from 'sdc-app/AppStore.js';
@@ -164,18 +163,10 @@ export default {
const newVersion = response[0].version ? response[0].version : version;
SoftwareProductActionHelper.loadSoftwareProductDetailsData(dispatch, {licenseModelId, licensingVersion});
- let isFetchImageDetails = (response[0].onboardingMethod === onboardingMethodTypes.HEAT);
- if (isFetchImageDetails) {
- // will only continue after we can properly build the navigation bar with the images links
- SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version: newVersion, isFetchImageDetails}).then(() => {
- SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version: newVersion});
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, {softwareProductId, licenseModelId, version: newVersion});
- });
- } else {
- SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version: newVersion, isFetchImageDetails});
- SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version: newVersion});
- setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, {softwareProductId, licenseModelId, version: newVersion});
- }
+
+ SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version: newVersion});
+ SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(dispatch, {softwareProductId, version: newVersion});
+ setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, {softwareProductId, licenseModelId, version: newVersion});
});
},
diff --git a/openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx b/openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx
index 1f0bef7a9f..aea5fc6406 100644
--- a/openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx
@@ -415,9 +415,9 @@ export default class OnboardingPunchOut {
handleStoreChange() {
let {currentScreen, licenseModelList, softwareProductList,
softwareProduct: {softwareProductEditor: {data = {onboardingMethod: ''}},
- softwareProductComponents: {componentsList, images: {imagesNavigationList}}, softwareProductAttachments: {heatSetup}}} = store.getState();
+ softwareProductComponents: {componentsList}, softwareProductAttachments: {heatSetup}}} = store.getState();
let {onboardingMethod} = data;
- let breadcrumbsData = {onboardingMethod, currentScreen, licenseModelList, softwareProductList, componentsList, heatSetup, imagesNavigationList};
+ let breadcrumbsData = {onboardingMethod, currentScreen, licenseModelList, softwareProductList, componentsList, heatSetup};
if (currentScreen.forceBreadCrumbsUpdate || !isEqual(breadcrumbsData, this.prevBreadcrumbsData) || this.breadcrumbsPrefixSelected) {
this.prevBreadcrumbsData = breadcrumbsData;
this.breadcrumbsPrefixSelected = false;
@@ -434,7 +434,7 @@ export default class OnboardingPunchOut {
}
}
- buildBreadcrumbs({currentScreen: {screen, props}, onboardingMethod, licenseModelList, softwareProductList, componentsList, heatSetup, imagesNavigationList}) {
+ buildBreadcrumbs({currentScreen: {screen, props}, onboardingMethod, licenseModelList, softwareProductList, componentsList, heatSetup}) {
let screenToBreadcrumb;
switch (screen) {
case enums.SCREEN.ONBOARDING_CATALOG:
@@ -646,15 +646,7 @@ export default class OnboardingPunchOut {
}, {
key: enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_MONITORING,
displayText: i18n('Monitoring')
- }].filter(item => {
- switch (item.key) {
- case enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_IMAGES:
- return (onboardingMethod === onboardingMethodTypes.MANUAL ||
- (imagesNavigationList && imagesNavigationList[props.componentId] === true));
- default:
- return true;
- }
- })
+ }]
}]
];
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js
index 4ba10c3a68..960090c2d8 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelConstants.js
@@ -14,6 +14,7 @@
* permissions and limitations under the License.
*/
import keyMirror from 'nfvo-utils/KeyMirror.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
export const actionTypes = keyMirror({
LICENSE_MODEL_LOADED: null,
@@ -31,3 +32,16 @@ export const navigationItems = keyMirror({
LICENSE_KEY_GROUPS: 'license-key-groups',
ACTIVITY_LOG: 'activity-log'
});
+
+export const thresholdUnitType = {
+ ABSOLUTE: 'Absolute',
+ PERCENTAGE: 'Percentage'
+};
+
+export const optionsInputValues = {
+ THRESHOLD_UNITS: [
+ {enum: '', title: i18n('please select…')},
+ {enum: thresholdUnitType.ABSOLUTE, title: 'Absolute'},
+ {enum: thresholdUnitType.PERCENTAGE, title: '%'}
+ ]
+}; \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js
index bd060a4c28..80beda22b5 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelReducer.js
@@ -35,6 +35,7 @@ import licenseKeyGroupsListReducer from './licenseKeyGroups/LicenseKeyGroupsList
import {createPlainDataReducer} from 'sdc-app/common/reducers/PlainDataReducer.js';
import {actionTypes as licenseModelOverviewConstants, selectedButton, VLM_DESCRIPTION_FORM} from './overview/LicenseModelOverviewConstants.js';
+import limitEditorReducer from './limits/LimitEditorReducer.js';
export default combineReducers({
licenseModelCreation: createPlainDataReducer(licenseModelCreationReducer),
@@ -81,5 +82,6 @@ export default combineReducers({
}
}
)}),
+ limitEditor: createPlainDataReducer(limitEditorReducer),
activityLog: activityLogReducer
});
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelValidations.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelValidations.js
new file mode 100644
index 0000000000..64bae3b6a0
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelValidations.js
@@ -0,0 +1,41 @@
+/*!
+ * 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 i18n from 'nfvo-utils/i18n/i18n.js';
+import {thresholdUnitType} from './LicenseModelConstants.js';
+import Validator from 'nfvo-utils/Validator.js';
+
+export function validateStartDate(value, state) {
+ if (state.data.expiryDate) {
+ if (!value) {
+ return {isValid: false, errorText: i18n('Start date has to be specified if expiry date is specified')};
+ }
+ }
+ return {isValid: true, errorText: ''};
+}
+
+export function thresholdValueValidation(value, state) {
+ let unit = state.data.thresholdUnits;
+ if (unit === thresholdUnitType.PERCENTAGE) {
+ return Validator.validate('thresholdValue', value, [
+ {type: 'numeric', data: true},
+ {type: 'maximum', data: 100},
+ {type: 'minimum', data: 0}]);
+ } else {
+ return Validator.validate('thresholdValue', value, [
+ {type: 'numeric', data: true},
+ ]);
+ }
+}
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 d85618c85f..39b3c15c6a 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js
@@ -26,7 +26,7 @@ export const mapStateToProps = ({licenseModelList, licenseModel: {licenseModelCr
let VLMNames = {};
for (let i = 0; i < licenseModelList.length; i++) {
- VLMNames[licenseModelList[i].vendorName] = licenseModelList[i].id;
+ VLMNames[licenseModelList[i].vendorName.toLowerCase()] = licenseModelList[i].id;
}
return {...licenseModelCreation, isFormValid: isFormValid, VLMNames};
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 a7c95f608d..a371d5635e 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js
@@ -17,6 +17,8 @@ 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';
+import {actionTypes as limitEditorActions} from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
+import getValue from 'nfvo-utils/getValue.js';
function baseUrl(licenseModelId, version) {
const restPrefix = Configuration.get('restPrefix');
@@ -28,18 +30,16 @@ function fetchEntitlementPoolsList(licenseModelId, version) {
return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}`);
}
-function postEntitlementPool(licenseModelId, entitlementPool, version) {
+function postEntitlementPool(licenseModelId, entitlementPool, version) {
return RestAPIUtil.post(baseUrl(licenseModelId, version), {
name: entitlementPool.name,
description: entitlementPool.description,
thresholdValue: entitlementPool.thresholdValue,
- thresholdUnits: entitlementPool.thresholdUnits,
+ thresholdUnits: getValue(entitlementPool.thresholdUnits),
entitlementMetric: entitlementPool.entitlementMetric,
increments: entitlementPool.increments,
- aggregationFunction: entitlementPool.aggregationFunction,
- operationalScope: entitlementPool.operationalScope,
+ operationalScope: getValue(entitlementPool.operationalScope),
time: entitlementPool.time,
- manufacturerReferenceNumber: entitlementPool.manufacturerReferenceNumber,
startDate: entitlementPool.startDate,
expiryDate: entitlementPool.expiryDate
});
@@ -47,17 +47,16 @@ function postEntitlementPool(licenseModelId, entitlementPool, version) {
function putEntitlementPool(licenseModelId, previousEntitlementPool, entitlementPool, version) {
+
return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${entitlementPool.id}`, {
name: entitlementPool.name,
description: entitlementPool.description,
thresholdValue: entitlementPool.thresholdValue,
- thresholdUnits: entitlementPool.thresholdUnits,
+ thresholdUnits: getValue(entitlementPool.thresholdUnits),
entitlementMetric: entitlementPool.entitlementMetric,
increments: entitlementPool.increments,
- aggregationFunction: entitlementPool.aggregationFunction,
- operationalScope: entitlementPool.operationalScope,
+ operationalScope: getValue(entitlementPool.operationalScope),
time: entitlementPool.time,
- manufacturerReferenceNumber: entitlementPool.manufacturerReferenceNumber,
startDate: entitlementPool.startDate,
expiryDate: entitlementPool.expiryDate
});
@@ -67,8 +66,43 @@ function deleteEntitlementPool(licenseModelId, entitlementPoolId, version) {
return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}`);
}
+function fetchLimitsList(licenseModelId, entitlementPoolId, version) {
+ return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits`);
+}
+
+function deleteLimit(licenseModelId, entitlementPoolId, version, limitId) {
+ return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits/${limitId}`);
+}
+
+function postLimit(licenseModelId, entitlementPoolId, version, limit) {
+ return RestAPIUtil.post(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits`, {
+ name: limit.name,
+ type: limit.type,
+ description: limit.description,
+ metric: limit.metric,
+ value: limit.value,
+ unit: limit.unit,
+ aggregationFunction: getValue(limit.aggregationFunction),
+ time: getValue(limit.time)
+ });
+}
+
+function putLimit(licenseModelId, entitlementPoolId, version, limit) {
+
+ return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${entitlementPoolId}/limits/${limit.id}`, {
+ name: limit.name,
+ type: limit.type,
+ description: limit.description,
+ metric: limit.metric,
+ value: limit.value,
+ unit: limit.unit,
+ aggregationFunction: getValue(limit.aggregationFunction),
+ time: getValue(limit.time)
+ });
+}
export default {
+
fetchEntitlementPoolsList(dispatch, {licenseModelId, version}) {
return fetchEntitlementPoolsList(licenseModelId, version).then(response => dispatch({
type: entitlementPoolsActionTypes.ENTITLEMENT_POOLS_LIST_LOADED,
@@ -76,7 +110,10 @@ export default {
}));
},
- openEntitlementPoolsEditor(dispatch, {entitlementPool} = {}) {
+ openEntitlementPoolsEditor(dispatch, {entitlementPool, licenseModelId, version} = {}) {
+ if (licenseModelId && version) {
+ this.fetchLimits(dispatch, {licenseModelId, version, entitlementPool});
+ }
dispatch({
type: entitlementPoolsActionTypes.entitlementPoolsEditor.OPEN,
entitlementPool
@@ -145,5 +182,32 @@ export default {
LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
this.fetchEntitlementPoolsList(dispatch, {licenseModelId, version});
});
+ },
+
+
+ fetchLimits(dispatch, {licenseModelId, version, entitlementPool}) {
+ return fetchLimitsList(licenseModelId, entitlementPool.id, version). then (response => {
+ dispatch({
+ type: entitlementPoolsActionTypes.entitlementPoolsEditor.LIMITS_LIST_LOADED,
+ response
+ });
+ });
+ },
+
+ submitLimit(dispatch, {licenseModelId, version, entitlementPool, limit}) {
+ const propmise = limit.id ? putLimit(licenseModelId,entitlementPool.id, version, limit)
+ : postLimit(licenseModelId,entitlementPool.id, version, limit);
+ return propmise.then(() => {
+ dispatch({
+ type: limitEditorActions.CLOSE
+ });
+ this.fetchLimits(dispatch, {licenseModelId, version, entitlementPool});
+ });
+ },
+
+ deleteLimit(dispatch, {licenseModelId, version, entitlementPool, limit}) {
+ return deleteLimit(licenseModelId,entitlementPool.id, version, limit.id).then(() => {
+ this.fetchLimits(dispatch, {licenseModelId, version, entitlementPool});
+ });
}
};
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 761614dfeb..de2a87ceaf 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsConstants.js
@@ -15,7 +15,7 @@
*/
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';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
export const actionTypes = keyMirror({
@@ -28,6 +28,7 @@ export const actionTypes = keyMirror({
OPEN: null,
CLOSE: null,
DATA_CHANGED: null,
+ LIMITS_LIST_LOADED: null
}
});
@@ -94,11 +95,6 @@ export const optionsInputValues = {
{enum: 'Units_TB', title: 'Units-TB'},
{enum: 'Units_GB', title: 'Units-GB'},
{enum: 'Units_MB', title: 'Units-MB'}
- ],
- THRESHOLD_UNITS: [
- {enum: '', title: i18n('please select…')},
- {enum: thresholdUnitType.ABSOLUTE, title: 'Absolute'},
- {enum: thresholdUnitType.PERCENTAGE, title: '%'}
]
};
@@ -112,6 +108,11 @@ export const extractUnits = (units) => {
return units === 'Absolute' ? '' : '%';
};
-export const SP_ENTITLEMENT_POOL_FORM = 'SPENTITLEMENTPOOL';
+export const tabIds = {
+ GENERAL: 'GENERAL',
+ SP_LIMITS: 'SP_LIMITS',
+ VENDOR_LIMITS: 'VENDOR_LIMITS',
+ ADD_LIMIT_BUTTON: 'ADD_LIMIT_BUTTON'
+};
-export const EP_TIME_FORMAT = 'MM/DD/YYYY';
+export const SP_ENTITLEMENT_POOL_FORM = 'SPENTITLEMENTPOOL'; \ No newline at end of file
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 f89cf8fbb5..23c260f793 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditor.js
@@ -18,10 +18,12 @@ import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
import EntitlementPoolsEditorView from './EntitlementPoolsEditorView.jsx';
import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import LimitEditorActionHelper from '../limits/LimitEditorActionHelper.js';
+
const mapStateToProps = ({licenseModel: {entitlementPool}}) => {
- let {data, genericFieldInfo, formReady} = entitlementPool.entitlementPoolEditor;
+ let {data, genericFieldInfo, formReady, limitsList} = entitlementPool.entitlementPoolEditor;
let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
@@ -33,7 +35,7 @@ const mapStateToProps = ({licenseModel: {entitlementPool}}) => {
const list = entitlementPool.entitlementPoolsList;
for (let i = 0; i < list.length; i++) {
- EPNames[list[i].name] = list[i].id;
+ EPNames[list[i].name.toLowerCase()] = list[i].id;
}
return {
@@ -42,7 +44,8 @@ const mapStateToProps = ({licenseModel: {entitlementPool}}) => {
previousData,
isFormValid,
formReady,
- EPNames
+ EPNames,
+ limitsList
};
};
@@ -50,11 +53,13 @@ const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
return {
onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
onCancel: () => EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch),
- onSubmit: ({previousEntitlementPool, entitlementPool}) => {
- EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch);
+ onSubmit: ({previousEntitlementPool, entitlementPool, keepOpen}) => {
+ if (!keepOpen) {EntitlementPoolsActionHelper.closeEntitlementPoolsEditor(dispatch);}
EntitlementPoolsActionHelper.saveEntitlementPool(dispatch, {licenseModelId, previousEntitlementPool, entitlementPool, version});
},
- onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
+ onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName),
+ onCloseLimitEditor: () => LimitEditorActionHelper.closeLimitsEditor(dispatch),
+ onOpenLimitEditor: (limit) => LimitEditorActionHelper.openLimitsEditor(dispatch, {limit})
};
};
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 bc9549765f..be100f6802 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorReducer.js
@@ -41,12 +41,7 @@ export default (state = {}, action) => {
'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}]
+ validations: [{type: 'maxLength', data: 1000}]
},
'increments' : {
isValid: true,
@@ -56,33 +51,18 @@ export default (state = {}, action) => {
'operationalScope' : {
isValid: true,
errorText: '',
- validations: [{type: 'required', data: true}]
+ validations: []
},
'thresholdUnits' : {
isValid: true,
errorText: '',
- validations: [{type: 'required', data: true}]
+ validations: []
},
'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}]
- },
+ validations: []
+ },
'startDate': {
isValid: true,
errorText: '',
@@ -106,6 +86,12 @@ export default (state = {}, action) => {
};
case actionTypes.entitlementPoolsEditor.CLOSE:
return {};
+
+ case actionTypes.entitlementPoolsEditor.LIMITS_LIST_LOADED:
+ return {
+ ...state,
+ limitsList: action.response.results
+ };
default:
return state;
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx
index e4b52fc439..aa1321c24a 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsEditorView.jsx
@@ -21,41 +21,39 @@ import Validator from 'nfvo-utils/Validator.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 Button from 'sdc-ui/lib/react/Button.js';
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, EP_TIME_FORMAT} from './EntitlementPoolsConstants.js';
-import {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+import {optionsInputValues as EntitlementPoolsOptionsInputValues, SP_ENTITLEMENT_POOL_FORM, tabIds} from './EntitlementPoolsConstants.js';
+import {optionsInputValues as LicenseModelOptionsInputValues} from '../LicenseModelConstants.js';
+import {validateStartDate, thresholdValueValidation} from '../LicenseModelValidations.js';
+import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
+import {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
+import Tabs from 'sdc-ui/lib/react/Tabs.js';
+import Tab from 'sdc-ui/lib/react/Tab.js';
+import EntitlementPoolsLimits from './EntitlementPoolsLimits.js';
+import {limitType, NEW_LIMIT_TEMP_ID} from '../limits/LimitEditorConstants.js';
const EntitlementPoolPropType = React.PropTypes.shape({
id: React.PropTypes.string,
name: React.PropTypes.string,
description: React.PropTypes.string,
- manufacturerReferenceNumber: React.PropTypes.string,
operationalScope: React.PropTypes.shape({
choices: React.PropTypes.array,
other: React.PropTypes.string
}),
- aggregationFunction: React.PropTypes.shape({
- choice: React.PropTypes.string,
- other: React.PropTypes.string
- }),
+ thresholdUnits: React.PropTypes.string,
+ thresholdValue: React.PropTypes.number,
increments: React.PropTypes.string,
- time: React.PropTypes.shape({
- choice: React.PropTypes.string,
- other: React.PropTypes.string
- }),
- entitlementMetric: React.PropTypes.shape({
- choice: React.PropTypes.string,
- other: React.PropTypes.string
- })
+ startDate: React.PropTypes.string,
+ expiryDate: React.PropTypes.string
});
-const EntitlementPoolsFormContent = ({data, genericFieldInfo, onDataChanged, validateName, validateChoiceWithOther, validateTimeOtherValue,
+const EntitlementPoolsFormContent = ({data, genericFieldInfo, onDataChanged, validateName,
thresholdValueValidation, validateStartDate}) => {
- let {
- name, description, manufacturerReferenceNumber, operationalScope , aggregationFunction, thresholdUnits, thresholdValue,
- increments, time, entitlementMetric, startDate, expiryDate} = data;
+ let {name, description, operationalScope, thresholdUnits, thresholdValue,
+ increments, startDate, expiryDate} = data;
return (
<GridSection>
<GridItem colSpan={2}>
@@ -73,12 +71,10 @@ const EntitlementPoolsFormContent = ({data, genericFieldInfo, onDataChanged, val
<InputOptions
onInputChange={()=>{}}
isMultiSelect={true}
-
- isRequired={true}
onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}},
- SP_ENTITLEMENT_POOL_FORM, {operationalScope: validateChoiceWithOther})}
+ SP_ENTITLEMENT_POOL_FORM)}
onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER],
- other: operationalScope}}, SP_ENTITLEMENT_POOL_FORM, {operationalScope: validateChoiceWithOther})}
+ other: operationalScope}}, SP_ENTITLEMENT_POOL_FORM)}
label={i18n('Operational Scope')}
data-test-id='create-ep-operational-scope'
type='select'
@@ -95,21 +91,21 @@ const EntitlementPoolsFormContent = ({data, genericFieldInfo, onDataChanged, val
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});}
+ if(thresholdValue && thresholdValue !== '') {
+ onDataChanged({thresholdValue: thresholdValue}, SP_ENTITLEMENT_POOL_FORM,{thresholdValue : thresholdValueValidation});
+ }}
}
value={thresholdUnits}
@@ -120,7 +116,7 @@ const EntitlementPoolsFormContent = ({data, genericFieldInfo, onDataChanged, val
groupClassName='bootstrap-input-options'
className='input-options-select'
type='select' >
- {EntitlementPoolsOptionsInputValues.THRESHOLD_UNITS.map(mtype =>
+ {LicenseModelOptionsInputValues.THRESHOLD_UNITS.map(mtype =>
<option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
</Input>
@@ -133,116 +129,46 @@ const EntitlementPoolsFormContent = ({data, genericFieldInfo, onDataChanged, val
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}
- isValid={genericFieldInfo.manufacturerReferenceNumber.isValid}
- errorText={genericFieldInfo.manufacturerReferenceNumber.errorText}
- 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>
- <GridItem colSpan={2} />
- <GridItem colSpan={2}>
- <Input
- type='date'
- label={i18n('Start Date')}
- value={startDate}
- dateFormat={EP_TIME_FORMAT}
- startDate={startDate}
- endDate={expiryDate}
- onChange={startDate => onDataChanged(
- {startDate: startDate ? startDate.format(EP_TIME_FORMAT) : ''},
- SP_ENTITLEMENT_POOL_FORM,
- {startDate: validateStartDate}
- )}
- isValid={genericFieldInfo.startDate.isValid}
- errorText={genericFieldInfo.startDate.errorText}
- selectsStart/>
- </GridItem>
- <GridItem colSpan={2}>
- <Input
- type='date'
- label={i18n('Expiry Date')}
- value={expiryDate}
- dateFormat={EP_TIME_FORMAT}
- startDate={startDate}
- endDate={expiryDate}
- onChange={expiryDate => {
- onDataChanged({expiryDate: expiryDate ? expiryDate.format(EP_TIME_FORMAT) : ''}, SP_ENTITLEMENT_POOL_FORM);
- onDataChanged({startDate}, SP_ENTITLEMENT_POOL_FORM, {startDate: validateStartDate});
- }}
- isValid={genericFieldInfo.expiryDate.isValid}
- errorText={genericFieldInfo.expiryDate.errorText}
- selectsEnd/>
- </GridItem>
+ <div className='date-section'>
+ <Input
+ type='date'
+ label={i18n('Start Date')}
+ value={startDate}
+ dateFormat={DATE_FORMAT}
+ startDate={startDate}
+ endDate={expiryDate}
+ onChange={startDate => onDataChanged(
+ {startDate: startDate ? startDate.format(DATE_FORMAT) : ''},
+ SP_ENTITLEMENT_POOL_FORM,
+ {startDate: validateStartDate}
+ )}
+ isValid={genericFieldInfo.startDate.isValid}
+ errorText={genericFieldInfo.startDate.errorText}
+ selectsStart/>
+ <Input
+ type='date'
+ label={i18n('Expiry Date')}
+ value={expiryDate}
+ dateFormat={DATE_FORMAT}
+ startDate={startDate}
+ endDate={expiryDate}
+ onChange={expiryDate => {
+ onDataChanged({expiryDate: expiryDate ? expiryDate.format(DATE_FORMAT) : ''}, SP_ENTITLEMENT_POOL_FORM);
+ onDataChanged({startDate}, SP_ENTITLEMENT_POOL_FORM, {startDate: validateStartDate});
+ }}
+ isValid={genericFieldInfo.expiryDate.isValid}
+ errorText={genericFieldInfo.expiryDate.errorText}
+ selectsEnd/>
+ </div>
+ </GridItem>
</GridSection>
);
};
@@ -263,42 +189,102 @@ class EntitlementPoolsEditorView extends React.Component {
data: {}
};
- render() {
- let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo} = this.props;
+ componentDidUpdate(prevProps) {
+ if (this.props.formReady && this.props.formReady !== prevProps.formReady) { // if form validation succeeded -> continue with submit
+ this.submit();
+ }
+ }
+
+ state = {
+ selectedTab: tabIds.GENERAL,
+ selectedLimit: ''
+ };
+ render() {
+ let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo, onCloseLimitEditor, limitsList = []} = this.props;
+ const {selectedTab} = this.state;
+ const isTabsDisabled = !data.id || !this.props.isFormValid;
return (
<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)}
- validateStartDate={(value, state)=> this.validateStartDate(value, state)}
- thresholdValueValidation={(value, state)=> this.thresholdValueValidation(value, state)}/>
- </Form>
+ <Tabs
+ type='menu'
+ activeTab={selectedTab}
+ onTabClick={(tabIndex)=>{
+ if (tabIndex === tabIds.ADD_LIMIT_BUTTON) {
+ this.onAddLimit();
+ } else {
+ this.setState({selectedTab: tabIndex});
+ this.setState({selectedLimit: ''});
+ onCloseLimitEditor();
+ }
+
+ }}
+ invalidTabs={[]}>
+ <Tab tabId={tabIds.GENERAL} data-test-id='general-tab' title={i18n('General')}>
+ {
+ genericFieldInfo && <Form
+ ref='validationForm'
+ hasButtons={false}
+ labledButtons={false}
+ isReadOnlyMode={isReadOnlyMode}
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.props.onValidateForm(SP_ENTITLEMENT_POOL_FORM) }
+ className='license-model-form entitlement-pools-form'>
+ <EntitlementPoolsFormContent
+ data={data}
+ genericFieldInfo={genericFieldInfo}
+ onDataChanged={onDataChanged}
+ validateName={(value) => this.validateName(value)}
+ validateStartDate={(value, state) => validateStartDate(value, state)}
+ thresholdValueValidation={(value, state) => thresholdValueValidation(value, state)}/>
+ </Form>
+ }
+ </Tab>
+ <Tab disabled={isTabsDisabled} tabId={tabIds.SP_LIMITS} data-test-id='sp-limits-tab' title={i18n('SP Limits')}>
+ {selectedTab === tabIds.SP_LIMITS &&
+ <EntitlementPoolsLimits
+ limitType={limitType.SERVICE_PROVIDER}
+ limitsList={limitsList.filter(item => item.type === limitType.SERVICE_PROVIDER)}
+ selectedLimit={this.state.selectedLimit}
+ onCloseLimitEditor={() => this.onCloseLimitEditor()}
+ onSelectLimit={limit => this.onSelectLimit(limit)}/>}
+ </Tab>
+ <Tab disabled={isTabsDisabled} tabId={tabIds.VENDOR_LIMITS} data-test-id='vendor-limits-tab' title={i18n('Vendor Limits')}>
+ {selectedTab === tabIds.VENDOR_LIMITS &&
+ <EntitlementPoolsLimits
+ limitType={limitType.VENDOR}
+ limitsList={limitsList.filter(item => item.type === limitType.VENDOR)}
+ selectedLimit={this.state.selectedLimit}
+ onCloseLimitEditor={() => this.onCloseLimitEditor()}
+ onSelectLimit={limit => this.onSelectLimit(limit)}/>}
+ </Tab>
+ {selectedTab !== tabIds.GENERAL ?
+ <Button disabled={this.state.selectedLimit} className='add-limit-button' tabId={tabIds.ADD_LIMIT_BUTTON} btnType='link' iconName='plus'>{i18n('Add Limit')}</Button> :
+ <div></div> // Render empty div to not break tabs
}
+ </Tabs>
+ <GridSection className='license-model-modal-buttons entitlement-pools-editor-buttons'>
+ {!this.state.selectedLimit && <Button btnType='default' disabled={!this.props.isFormValid} onClick={() => this.submit()} type='reset'>{i18n('Save')}</Button>}
+ <Button btnType={this.state.selectedLimit ? 'default' : 'outline'} onClick={() => this.props.onCancel()} type='reset'>
+ {i18n('Cancel')}
+ </Button>
+ </GridSection>
</div>
);
}
submit() {
- const {data: entitlementPool, previousData: previousEntitlementPool} = this.props;
- this.props.onSubmit({entitlementPool, previousEntitlementPool});
+ const {data: entitlementPool, previousData: previousEntitlementPool, formReady} = this.props;
+
+ if (!formReady) {
+ this.props.onValidateForm(SP_ENTITLEMENT_POOL_FORM);
+ } else {
+ this.props.onSubmit({entitlementPool, previousEntitlementPool});
+ }
+
+
}
validateName(value) {
@@ -309,52 +295,26 @@ class EntitlementPoolsEditorView extends React.Component {
{isValid: false, errorText: i18n('Entitlement pool by the name \'' + value + '\' already exists. Entitlement pool name must be unique')};
}
- validateStartDate(value, state) {
- if (state.data.expiryDate) {
- if (!value) {
- return {isValid: false, errorText: i18n('Start date has to be specified if expiry date is specified')};
- }
+ onSelectLimit(limit) {
+ if (limit.id === this.state.selectedLimit) {
+ this.setState({selectedLimit: ''});
+ return;
}
- return {isValid: true, errorText: ''};
+ this.setState({selectedLimit: limit.id});
+ this.props.onOpenLimitEditor(limit);
}
- validateTimeOtherValue(value) {
- return Validator.validate('time', value.other, [{type: 'required', data: true}, {type: 'numeric', data: true}]);
+ onCloseLimitEditor() {
+ this.setState({selectedLimit: ''});
+ this.props.onCloseLimitEditor();
}
- 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}]);
- }
+ onAddLimit() {
+ this.setState({selectedLimit: NEW_LIMIT_TEMP_ID});
+ this.props.onOpenLimitEditor();
}
- 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}]);
- }
- }
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsLimits.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsLimits.js
new file mode 100644
index 0000000000..ae53a753c0
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsLimits.js
@@ -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 {connect} from 'react-redux';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import Limits from 'sdc-app/onboarding/licenseModel/limits/Limits.jsx';
+import {actionTypes as globalModalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import EntitlementPoolsActionHelper from './EntitlementPoolsActionHelper.js';
+
+const mapStateToProps = ({licenseModel: {entitlementPool: {entitlementPoolEditor: {data}}, limitEditor}, currentScreen}) => {
+ let {props: {licenseModelId, version}} = currentScreen;
+ return {
+ parent: data,
+ limitEditor,
+ licenseModelId,
+ version
+ };
+};
+
+const mapActionsToProps = (dispatch) => {
+ return {
+ onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
+ onSubmit: (limit, entitlementPool, licenseModelId, version) => EntitlementPoolsActionHelper.submitLimit(dispatch,
+ {
+ limit,
+ entitlementPool,
+ licenseModelId,
+ version}),
+ onDelete: ({limit, parent, licenseModelId, version, onCloseLimitEditor, selectedLimit}) => dispatch({
+ type: globalModalActionTypes.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: i18n(`Are you sure you want to delete ${limit.name}?`),
+ confirmationButtonText: i18n('Delete'),
+ title: i18n('Warning'),
+ onConfirmed: ()=> EntitlementPoolsActionHelper.deleteLimit(dispatch, {limit, entitlementPool: parent, licenseModelId, version}).then(() =>
+ selectedLimit === limit.id && onCloseLimitEditor()
+ )
+ }
+ })
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(Limits); \ No newline at end of file
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 993ed48f2b..62c6663833 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditor.js
@@ -39,7 +39,7 @@ const mapStateToProps = ({licenseModel: {entitlementPool, licenseModelEditor}})
const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
return {
onAddEntitlementPoolClick: () => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch),
- onEditEntitlementPoolClick: entitlementPool => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch, {entitlementPool}),
+ onEditEntitlementPoolClick: entitlementPool => EntitlementPoolsActionHelper.openEntitlementPoolsEditor(dispatch, {entitlementPool, licenseModelId, version}),
onDeleteEntitlementPool: entitlementPool => dispatch({
type: globalMoadlActions.GLOBAL_MODAL_WARNING,
data:{
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 55fd11b8bb..c730d669c7 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsListEditorView.jsx
@@ -21,7 +21,7 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
import EntitlementPoolsEditor from './EntitlementPoolsEditor.js';
-import {extractUnits, extractValue} from './EntitlementPoolsConstants';
+import {extractUnits} from './EntitlementPoolsConstants';
class EntitlementPoolsListEditorView extends React.Component {
static propTypes = {
@@ -60,7 +60,7 @@ class EntitlementPoolsListEditorView extends React.Component {
isReadOnlyMode={isReadOnlyMode}>
{this.filterList().map(entitlementPool => this.renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode))}
</ListEditorView>
- <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal entitlement-pools-modal'>
+ <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal license-model-modal entitlement-pools-modal'>
<Modal.Header>
<Modal.Title>{`${isModalInEditMode ? i18n('Edit Entitlement Pool') : i18n('Create New Entitlement Pool')}`}</Modal.Title>
</Modal.Header>
@@ -91,8 +91,7 @@ class EntitlementPoolsListEditorView extends React.Component {
}
renderEntitlementPoolListItem(entitlementPool, isReadOnlyMode) {
- let {id, name, description, thresholdValue, thresholdUnits, entitlementMetric, aggregationFunction,
- manufacturerReferenceNumber, time} = entitlementPool;
+ let {id, name, description, thresholdValue, thresholdUnits} = entitlementPool;
let {onEditEntitlementPoolClick, onDeleteEntitlementPool} = this.props;
return (
<ListEditorItemView
@@ -109,13 +108,7 @@ class EntitlementPoolsListEditorView extends React.Component {
<div className='list-editor-item-view-field'>
<div className='title'>{i18n('Entitlement')}</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'>
- <div className='title'>{i18n('Manufacturer Reference Number')}</div>
- <div className='text contract-number'>{manufacturerReferenceNumber}</div>
+ <div className='entitlement-pools-count'>{thresholdValue && `${thresholdValue} ${extractUnits(thresholdUnits)}`}</div>
</div>
<div className='list-editor-item-view-field'>
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 c6249c98ca..6edb1e1f0c 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditor.js
@@ -34,7 +34,7 @@ export const mapStateToProps = ({licenseModel: {featureGroup, entitlementPool, l
}
for (let i = 0; i < list.length; i++) {
- FGNames[list[i].name] = list[i].id;
+ FGNames[list[i].name.toLowerCase()] = list[i].id;
}
for (let field in genericFieldInfo) {
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 d69548442c..6a5ee4617c 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupEditorView.jsx
@@ -15,7 +15,7 @@
*/
import React from 'react';
import Tabs from 'nfvo-components/input/validation/Tabs.jsx';
-import Tab from 'react-bootstrap/lib/Tab.js';
+import Tab from 'sdc-ui/lib/react/Tab.js';
import GridSection from 'nfvo-components/grid/GridSection.jsx';
import GridItem from 'nfvo-components/grid/GridItem.jsx';
import {TabsForm as Form} from 'nfvo-components/input/validation/Form.jsx';
@@ -31,12 +31,13 @@ const FeatureGroupsPropType = React.PropTypes.shape({
name: React.PropTypes.string,
description: React.PropTypes.string,
partNumber: React.PropTypes.string,
+ manufacturerReferenceNumber: 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;
+ let {name, description, partNumber, manufacturerReferenceNumber} = data;
return (
<GridSection>
<GridItem colSpan={2}>
@@ -51,6 +52,8 @@ const GeneralTab = ({data = {}, onDataChanged, genericFieldInfo, validateName})
isRequired={true}
isValid={genericFieldInfo.name.isValid}
errorText={genericFieldInfo.name.errorText} />
+ </GridItem>
+ <GridItem colSpan={2}>
<Input
groupClassName='field-section'
className='description-field'
@@ -60,9 +63,10 @@ const GeneralTab = ({data = {}, onDataChanged, genericFieldInfo, validateName})
value={description}
name='feature-group-description'
type='textarea'
- isRequired={true}
isValid={genericFieldInfo.description.isValid}
errorText={genericFieldInfo.description.errorText} />
+ </GridItem>
+ <GridItem colSpan={2}>
<Input
groupClassName='field-section'
onChange={partNumber => onDataChanged({partNumber}, FG_EDITOR_FORM)}
@@ -74,6 +78,18 @@ const GeneralTab = ({data = {}, onDataChanged, genericFieldInfo, validateName})
isValid={genericFieldInfo.partNumber.isValid}
errorText={genericFieldInfo.partNumber.errorText} />
</GridItem>
+ <GridItem colSpan={2}>
+ <Input
+ groupClassName='field-section'
+ onChange={manufacturerReferenceNumber => onDataChanged({manufacturerReferenceNumber}, FG_EDITOR_FORM)}
+ label={i18n('Manufacturer Reference Number')}
+ data-test-id='create-fg-reference-number'
+ value={manufacturerReferenceNumber}
+ isRequired={true}
+ type='text'
+ isValid={genericFieldInfo.manufacturerReferenceNumber.isValid}
+ errorText={genericFieldInfo.manufacturerReferenceNumber.errorText} />
+ </GridItem>
</GridSection>
);
};
@@ -94,7 +110,7 @@ const EntitlementPoolsTab = ({entitlementPoolsList, data, onDataChanged, isReadO
);
} else {
return (
- <p>{i18n('There is no available entitlement pools')}</p>
+ <p>{i18n('There are no available entitlement pools')}</p>
);
}
};
@@ -115,7 +131,7 @@ const LKGTab = ({licenseKeyGroupsList, data, onDataChanged, isReadOnlyMode}) =>
);
} else {
return (
- <p>{i18n('There is no available licsense key groups')}</p>
+ <p>{i18n('There are no available license key groups')}</p>
);
}
};
@@ -166,22 +182,22 @@ class FeatureGroupEditorView extends React.Component {
labledButtons={true}
isReadOnlyMode={isReadOnlyMode}
name='feature-group-validation-form'
- className='feature-group-form'>
- <Tabs activeKey={onTabSelect ? selectedTab : undefined} onSelect={onTabSelect} invalidTabs={invalidTabs} id='vlmFGValTabs' >
- <Tab eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL} title={i18n('General')} >
+ className='license-model-form feature-group-form'>
+ <Tabs activeTab={onTabSelect ? selectedTab : undefined} onTabClick={onTabSelect} invalidTabs={invalidTabs} id='vlmFGValTabs' >
+ <Tab tabId={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL} title={i18n('General')} >
<fieldset disabled={isReadOnlyMode}>
<GeneralTab data={data} onDataChanged={onDataChanged} genericFieldInfo={genericFieldInfo} validateName={(value)=> this.validateName(value)}/>
</fieldset>
</Tab>
<Tab
- eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS}
+ tabId={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.ENTITLEMENT_POOLS}
title={i18n('Entitlement Pools')} >
<fieldset disabled={isReadOnlyMode}>
<EntitlementPoolsTab isReadOnlyMode={isReadOnlyMode} data={data} onDataChanged={onDataChanged} entitlementPoolsList={entitlementPoolsList} />
</fieldset>
</Tab>
<Tab
- eventKey={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENSE_KEY_GROUPS}
+ tabId={FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.LICENSE_KEY_GROUPS}
title={i18n('License Key Groups')} >
<fieldset disabled={isReadOnlyMode}>
<LKGTab isReadOnlyMode={isReadOnlyMode} data={data} onDataChanged={onDataChanged} licenseKeyGroupsList={licenseKeyGroupsList} />
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 f883bd7a14..9844290a25 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupListEditorView.jsx
@@ -65,7 +65,7 @@ class FeatureGroupListEditorView extends React.Component {
{this.filterList().map(listItem => this.renderFeatureGroupListItem(listItem, isReadOnlyMode, version))}
</ListEditorView>
{featureGroupsModal.show && <Modal show={featureGroupsModal.show} bsSize='large' animation={true}
- className='onborading-modal feature-group-modal'>
+ className='onborading-modal license-model-modal feature-group-modal'>
<Modal.Header>
<Modal.Title>{`${featureGroupsModal.editMode ? i18n('Edit Feature Group') : i18n('Create New Feature Group')}`}</Modal.Title>
</Modal.Header>
@@ -84,7 +84,7 @@ class FeatureGroupListEditorView extends React.Component {
renderFeatureGroupListItem(listItem, isReadOnlyMode, version) {
- let {name, description, entitlementPoolsIds = [], licenseKeyGroupsIds = []} = listItem;
+ let {name, description, manufacturerReferenceNumber, entitlementPoolsIds = [], licenseKeyGroupsIds = []} = listItem;
return (
<ListEditorItemView
key={listItem.id}
@@ -111,9 +111,19 @@ class FeatureGroupListEditorView extends React.Component {
</div>
<div className='list-editor-item-view-field'>
+ <div className='feature-groups-count-field'>
+ <div className='title'>{i18n('Manufacturer Reference')}</div>
+ <div className='title'>{i18n('Number')}</div>
+ <div className='feature-groups-count-ep'>{manufacturerReferenceNumber}</div>
+ </div>
+ </div>
+
+ <div className='list-editor-item-view-field'>
<div className='title'>{i18n('Description')}</div>
<div className='text description'>{description}</div>
</div>
+
+
</ListEditorItemView>
);
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 a2015787a6..b8c03750fb 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsActionHelper.js
@@ -39,6 +39,7 @@ function addFeatureGroup(licenseModelId, featureGroup, version) {
name: featureGroup.name,
description: featureGroup.description,
partNumber: featureGroup.partNumber,
+ manufacturerReferenceNumber: featureGroup.manufacturerReferenceNumber,
addedLicenseKeyGroupsIds: featureGroup.licenseKeyGroupsIds,
addedEntitlementPoolsIds: featureGroup.entitlementPoolsIds
});
@@ -54,6 +55,7 @@ function updateFeatureGroup(licenseModelId, previousFeatureGroup, featureGroup,
name: featureGroup.name,
description: featureGroup.description,
partNumber: featureGroup.partNumber,
+ manufacturerReferenceNumber: featureGroup.manufacturerReferenceNumber,
addedLicenseKeyGroupsIds: licenseKeyGroupsIds.filter(licenseKeyGroupId => prevLicenseKeyGroupsIds.indexOf(licenseKeyGroupId) === -1),
removedLicenseKeyGroupsIds: prevLicenseKeyGroupsIds.filter(prevLicenseKeyGroupId => licenseKeyGroupsIds.indexOf(prevLicenseKeyGroupId) === -1),
addedEntitlementPoolsIds: entitlementPoolsIds.filter(entitlementPoolId => prevEntitlementPoolsIds.indexOf(entitlementPoolId) === -1),
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 001bd20d44..5688fc0f16 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/featureGroups/FeatureGroupsEditorReducer.js
@@ -30,7 +30,7 @@ export default (state = {}, action) => {
'description': {
isValid: true,
errorText: '',
- validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}],
+ validations: [{type: 'maxLength', data: 1000}],
tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
},
'partNumber': {
@@ -39,6 +39,12 @@ export default (state = {}, action) => {
validations: [{type: 'required', data: true}],
tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
},
+ 'manufacturerReferenceNumber': {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 100}],
+ tabId: FeatureGroupStateConstants.SELECTED_FEATURE_GROUP_TAB.GENERAL
+ },
'name': {
isValid: true,
errorText: '',
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 998d5f0e8d..40bef2c181 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementConstants.js
@@ -15,7 +15,7 @@
*/
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';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
export const actionTypes = keyMirror({
LICENSE_AGREEMENT_LIST_LOADED: null,
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 aada8ddca1..7d70da6ea5 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditor.js
@@ -32,7 +32,7 @@ export const mapStateToProps = ({licenseModel: {licenseAgreement, featureGroup}}
}
for (let i = 0; i < list.length; i++) {
- LANames[list[i].name] = list[i].id;
+ LANames[list[i].name.toLowerCase()] = list[i].id;
}
const {featureGroupsList = []} = featureGroup;
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 e02935c579..5be140550a 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorReducer.js
@@ -26,7 +26,7 @@ export default (state = {}, action) => {
'description' : {
isValid: true,
errorText: '',
- validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}],
+ validations: [{type: 'maxLength', data: 1000}],
tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
},
'requirementsAndConstrains' : {
@@ -38,7 +38,7 @@ export default (state = {}, action) => {
'licenseTerm' : {
isValid: true,
errorText: '',
- validations: [],
+ validations: [{type: 'required', data: true}],
tabId: LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL
},
'name' : {
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 42a33fd509..a15e5daa4e 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementEditorView.jsx
@@ -19,7 +19,7 @@ import GridSection from 'nfvo-components/grid/GridSection.jsx';
import GridItem from 'nfvo-components/grid/GridItem.jsx';
import {TabsForm as 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 Tab from 'sdc-ui/lib/react/Tab.js';
import Input from 'nfvo-components/input/validation/Input.jsx';
import DualListboxView from 'nfvo-components/input/dualListbox/DualListboxView.jsx';
import i18n from 'nfvo-utils/i18n/i18n.js';
@@ -96,7 +96,6 @@ const GeneralTabContent = ({data, genericFieldInfo, onDataChanged, validateName,
overlayPos='bottom'
data-test-id='create-la-description'
name='license-agreement-description'
- isRequired={true}
type='textarea'/>
</GridItem>
</GridSection>
@@ -145,10 +144,10 @@ class LicenseAgreementEditorView extends React.Component {
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} >
+ className='license-model-form license-agreement-form'>
+ <Tabs activeTab={onTabSelect ? selectedTab : undefined} onTabClick={onTabSelect} invalidTabs={this.props.invalidTabs} >
<Tab
- eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL}
+ tabId={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.GENERAL}
data-test-id='general-tab'
title={i18n('General')}>
<fieldset disabled={isReadOnlyMode}>
@@ -157,7 +156,7 @@ class LicenseAgreementEditorView extends React.Component {
</fieldset>
</Tab>
<Tab
- eventKey={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS}
+ tabId={LicenseAgreementEnums.SELECTED_LICENSE_AGREEMENT_TAB.FEATURE_GROUPS}
data-test-id='feature-group-tab'
title={i18n('Feature Groups')}>
<fieldset disabled={isReadOnlyMode}>
@@ -168,7 +167,7 @@ class LicenseAgreementEditorView extends React.Component {
selectedValuesList={data.featureGroupsIds}
availableList={featureGroupsList}
onChange={ selectedValuesList => onDataChanged( { featureGroupsIds: selectedValuesList }, LA_EDITOR_FORM )}/> :
- <p>{i18n('There is no available feature groups')}</p>}
+ <p>{i18n('There are no available feature groups')}</p>}
</fieldset>
</Tab>
</Tabs>
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 192d2ded99..6247723d72 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseAgreement/LicenseAgreementListEditorView.jsx
@@ -59,7 +59,7 @@ class LicenseAgreementListEditorView extends React.Component {
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 show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal license-model-modal license-agreement-modal'>
<Modal.Header>
<Modal.Title>{`${isModalInEditMode ? i18n('Edit License Agreement') : i18n('Create New License Agreement')}`}</Modal.Title>
</Modal.Header>
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 dd2a5c6003..f5017f6d7a 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js
@@ -17,6 +17,8 @@ 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';
+import {actionTypes as limitEditorActions} from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
+import getValue from 'nfvo-utils/getValue.js';
function baseUrl(licenseModelId, version) {
const restPrefix = Configuration.get('restPrefix');
@@ -36,8 +38,13 @@ function postLicenseKeyGroup(licenseModelId, licenseKeyGroup, version) {
return RestAPIUtil.post(baseUrl(licenseModelId, version), {
name: licenseKeyGroup.name,
description: licenseKeyGroup.description,
- operationalScope: licenseKeyGroup.operationalScope,
- type: licenseKeyGroup.type
+ operationalScope: getValue(licenseKeyGroup.operationalScope),
+ type: licenseKeyGroup.type,
+ increments: licenseKeyGroup.increments,
+ thresholdValue: licenseKeyGroup.thresholdValue,
+ thresholdUnits: getValue(licenseKeyGroup.thresholdUnits),
+ startDate: licenseKeyGroup.startDate,
+ expiryDate: licenseKeyGroup.expiryDate
});
}
@@ -45,11 +52,50 @@ function putLicenseKeyGroup(licenseModelId, licenseKeyGroup, version) {
return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${licenseKeyGroup.id}`, {
name: licenseKeyGroup.name,
description: licenseKeyGroup.description,
- operationalScope: licenseKeyGroup.operationalScope,
- type: licenseKeyGroup.type
+ operationalScope: getValue(licenseKeyGroup.operationalScope),
+ type: licenseKeyGroup.type,
+ increments: licenseKeyGroup.increments,
+ thresholdValue: licenseKeyGroup.thresholdValue,
+ thresholdUnits: getValue(licenseKeyGroup.thresholdUnits),
+ startDate: licenseKeyGroup.startDate,
+ expiryDate: licenseKeyGroup.expiryDate
});
}
+function fetchLimitsList(licenseModelId, licenseKeyGroupId, version) {
+ return RestAPIUtil.fetch(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits`);
+}
+
+function deleteLimit(licenseModelId, licenseKeyGroupId, version, limitId) {
+ return RestAPIUtil.destroy(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits/${limitId}`);
+}
+
+function postLimit(licenseModelId, licenseKeyGroupId, version, limit) {
+ return RestAPIUtil.post(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits`, {
+ name: limit.name,
+ type: limit.type,
+ description: limit.description,
+ metric: limit.metric,
+ value: limit.value,
+ unit: limit.unit,
+ aggregationFunction: getValue(limit.aggregationFunction),
+ time: getValue(limit.time)
+ });
+}
+
+function putLimit(licenseModelId, licenseKeyGroupId, version, limit) {
+
+ return RestAPIUtil.put(`${baseUrl(licenseModelId, version)}/${licenseKeyGroupId}/limits/${limit.id}`, {
+ name: limit.name,
+ type: limit.type,
+ description: limit.description,
+ metric: limit.metric,
+ value: limit.value,
+ unit: limit.unit,
+ aggregationFunction: getValue(limit.aggregationFunction),
+ time: getValue(limit.time)
+ });
+}
export default {
fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version}) {
@@ -59,7 +105,10 @@ export default {
}));
},
- openLicenseKeyGroupsEditor(dispatch, {licenseKeyGroup} = {}) {
+ openLicenseKeyGroupsEditor(dispatch, {licenseKeyGroup, licenseModelId, version} = {}) {
+ if (licenseModelId && version) {
+ this.fetchLimits(dispatch, {licenseModelId, version, licenseKeyGroup});
+ }
dispatch({
type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.OPEN,
licenseKeyGroup
@@ -124,5 +173,34 @@ export default {
LicenseModelActionHelper.fetchLicenseModelById(dispatch, {licenseModelId, version}).then(() => {
this.fetchLicenseKeyGroupsList(dispatch, {licenseModelId, version});
});
+ },
+
+
+ fetchLimits(dispatch, {licenseModelId, version, licenseKeyGroup}) {
+ return fetchLimitsList(licenseModelId, licenseKeyGroup.id, version).then(response => {
+ dispatch({
+ type: licenseKeyGroupsConstants.licenseKeyGroupsEditor.LIMITS_LIST_LOADED,
+ response
+ });
+ });
+ },
+
+ submitLimit(dispatch, {licenseModelId, version, licenseKeyGroup, limit}) {
+ const promise = limit.id ? putLimit(licenseModelId,licenseKeyGroup.id, version, limit) :
+ postLimit(licenseModelId,licenseKeyGroup.id, version, limit);
+ return promise.then(() => {
+ dispatch({
+ type: limitEditorActions.CLOSE
+ });
+ this.fetchLimits(dispatch, {licenseModelId, version, licenseKeyGroup});
+ });
+ },
+
+ deleteLimit(dispatch, {licenseModelId, version, licenseKeyGroup, limit}) {
+ return deleteLimit(licenseModelId,licenseKeyGroup.id, version, limit.id).then(() => {
+ this.fetchLimits(dispatch, {licenseModelId, version, licenseKeyGroup});
+ });
}
+
+
};
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 50d1fe8625..c376cb3fbc 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsConstants.js
@@ -15,7 +15,7 @@
*/
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';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
export const actionTypes = keyMirror({
@@ -28,6 +28,7 @@ export const actionTypes = keyMirror({
OPEN: null,
CLOSE: null,
DATA_CHANGED: null,
+ LIMITS_LIST_LOADED: null
}
});
@@ -77,3 +78,10 @@ export const getOperationalScopes = (operationalScope) => {
return allOpScopes;
}
};
+
+export const tabIds = {
+ GENERAL: 'GENERAL',
+ SP_LIMITS: 'SP_LIMITS',
+ VENDOR_LIMITS: 'VENDOR_LIMITS',
+ ADD_LIMIT_BUTTON: 'ADD_LIMIT_BUTTON'
+};
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 aef1532dc1..028fa9d3e4 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditor.js
@@ -16,12 +16,13 @@
import {connect} from 'react-redux';
import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
import LicenseKeyGroupsEditorView from './LicenseKeyGroupsEditorView.jsx';
+import LimitEditorActionHelper from '../limits/LimitEditorActionHelper.js';
import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
const mapStateToProps = ({licenseModel: {licenseKeyGroup}}) => {
- let {data, genericFieldInfo, formReady} = licenseKeyGroup.licenseKeyGroupsEditor;
+ let {data, genericFieldInfo, formReady, limitsList} = licenseKeyGroup.licenseKeyGroupsEditor;
let previousData, LKGNames = {};
const licenseKeyGroupId = data ? data.id : null;
@@ -33,7 +34,7 @@ const mapStateToProps = ({licenseModel: {licenseKeyGroup}}) => {
const list = licenseKeyGroup.licenseKeyGroupsList;
for (let i = 0; i < list.length; i++) {
- LKGNames[list[i].name] = list[i].id;
+ LKGNames[list[i].name.toLowerCase()] = list[i].id;
}
return {
@@ -42,7 +43,8 @@ const mapStateToProps = ({licenseModel: {licenseKeyGroup}}) => {
genericFieldInfo,
isFormValid,
formReady,
- LKGNames
+ LKGNames,
+ limitsList
};
};
@@ -50,11 +52,13 @@ const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
return {
onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
onCancel: () => LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch),
- onSubmit: ({previousLicenseKeyGroup, licenseKeyGroup}) => {
- LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch);
+ onSubmit: ({previousLicenseKeyGroup, licenseKeyGroup, keepOpen}) => {
+ if (!keepOpen) {LicenseKeyGroupsActionHelper.closeLicenseKeyGroupEditor(dispatch);}
LicenseKeyGroupsActionHelper.saveLicenseKeyGroup(dispatch, {licenseModelId, previousLicenseKeyGroup, licenseKeyGroup, version});
},
- onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
+ onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName),
+ onCloseLimitEditor: () => LimitEditorActionHelper.closeLimitsEditor(dispatch),
+ onOpenLimitEditor: (limit) => LimitEditorActionHelper.openLimitsEditor(dispatch, {limit})
};
};
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 090c971c65..b1a22f3d9a 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorReducer.js
@@ -14,20 +14,30 @@
* permissions and limitations under the License.
*/
import {actionTypes, defaultState, LKG_FORM_NAME} from './LicenseKeyGroupsConstants.js';
+import moment from 'moment';
+import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
export default (state = {}, action) => {
switch (action.type) {
case actionTypes.licenseKeyGroupsEditor.OPEN:
+ let licenseKeyGroupData = {...action.licenseKeyGroup};
+ let {startDate, expiryDate} = licenseKeyGroupData;
+ if (startDate) {
+ licenseKeyGroupData.startDate = moment(startDate, DATE_FORMAT).format(DATE_FORMAT);
+ }
+ if (expiryDate) {
+ licenseKeyGroupData.expiryDate = moment(expiryDate, DATE_FORMAT).format(DATE_FORMAT);
+ }
return {
...state,
- data: action.licenseKeyGroup ? {...action.licenseKeyGroup} : defaultState.licenseKeyGroupsEditor,
+ data: action.licenseKeyGroup ? licenseKeyGroupData : defaultState.licenseKeyGroupsEditor,
formReady: null,
formName: LKG_FORM_NAME,
genericFieldInfo: {
'description' : {
isValid: true,
errorText: '',
- validations: [{type: 'required', data: true}, {type: 'maxLength', data: 1000}]
+ validations: [{type: 'maxLength', data: 1000}]
},
'name' : {
isValid: true,
@@ -43,9 +53,39 @@ export default (state = {}, action) => {
isValid: true,
errorText: '',
validations: []
+ },
+ 'thresholdUnits' : {
+ isValid: true,
+ errorText: '',
+ validations: []
+ },
+ 'thresholdValue' : {
+ isValid: true,
+ errorText: '',
+ validations: []
+ },
+ 'increments' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'maxLength', data: 120}]
+ },
+ 'startDate': {
+ isValid: true,
+ errorText: '',
+ validations: []
+ },
+ 'expiryDate': {
+ isValid: true,
+ errorText: '',
+ validations: []
}
}
};
+ case actionTypes.licenseKeyGroupsEditor.LIMITS_LIST_LOADED:
+ return {
+ ...state,
+ limitsList: action.response.results
+ };
case actionTypes.licenseKeyGroupsEditor.CLOSE:
return {};
default:
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 b95efd0f9c..647e205cb5 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsEditorView.jsx
@@ -17,27 +17,43 @@ import React from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
import Validator from 'nfvo-utils/Validator.js';
+import Tabs from 'sdc-ui/lib/react/Tabs.js';
+import Tab from 'sdc-ui/lib/react/Tab.js';
+
+import Button from 'sdc-ui/lib/react/Button.js';
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 {optionsInputValues as licenseKeyGroupOptionsInputValues, LKG_FORM_NAME, tabIds} from './LicenseKeyGroupsConstants.js';
+import {optionsInputValues as LicenseModelOptionsInputValues} from '../LicenseModelConstants.js';
+import {validateStartDate, thresholdValueValidation} from '../LicenseModelValidations.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({
+import {DATE_FORMAT} from 'sdc-app/onboarding/OnboardingConstants.js';
+
+import LicenseKeyGroupsLimits from './LicenseKeyGroupsLimits.js';
+import {limitType, NEW_LIMIT_TEMP_ID} from '../limits/LimitEditorConstants.js';
+
+ const LicenseKeyGroupPropType = React.PropTypes.shape({
id: React.PropTypes.string,
name: React.PropTypes.string,
description: React.PropTypes.string,
+ increments: React.PropTypes.string,
operationalScope: React.PropTypes.shape({
choices: React.PropTypes.array,
other: React.PropTypes.string
}),
- type: React.PropTypes.string
+ type: React.PropTypes.string,
+ thresholdUnits: React.PropTypes.string,
+ thresholdValue: React.PropTypes.number,
+ startDate: React.PropTypes.string,
+ expiryDate: React.PropTypes.string
});
-const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, validateName, validateOperationalScope}) => {
- let {name, description, operationalScope, type} = data;
+const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, validateName, validateStartDate, thresholdValueValidation}) => {
+ let {name, description, increments, operationalScope, type, thresholdUnits, thresholdValue, startDate, expiryDate} = data;
return (
<GridSection>
<GridItem colSpan={2}>
@@ -55,11 +71,10 @@ const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, vali
<InputOptions
onInputChange={()=>{}}
isMultiSelect={true}
- isRequired={true}
onEnumChange={operationalScope => onDataChanged({operationalScope:{choices: operationalScope, other: ''}},
- LKG_FORM_NAME, {operationalScope: validateOperationalScope})}
+ LKG_FORM_NAME)}
onOtherChange={operationalScope => onDataChanged({operationalScope:{choices: [optionInputOther.OTHER],
- other: operationalScope}}, LKG_FORM_NAME, {operationalScope: validateOperationalScope})}
+ other: operationalScope}}, LKG_FORM_NAME)}
label={i18n('Operational Scope')}
data-test-id='create-lkg-operational-scope'
type='select'
@@ -77,7 +92,6 @@ const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, vali
value={description}
isValid={genericFieldInfo.description.isValid}
errorText={genericFieldInfo.description.errorText}
- isRequired={true}
type='textarea'
overlayPos='bottom' />
</GridItem>
@@ -101,6 +115,82 @@ const LicenseKeyGroupFormContent = ({data, onDataChanged, genericFieldInfo, vali
}
</Input>
</GridItem>
+ <GridItem>
+ <Input
+ onChange={e => {
+ // setting the unit to the correct value
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onDataChanged({thresholdUnits: val}, LKG_FORM_NAME);
+ // TODO make sure that the value is valid too
+ onDataChanged({thresholdValue: thresholdValue}, LKG_FORM_NAME,{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' >
+ {LicenseModelOptionsInputValues.THRESHOLD_UNITS.map(mtype =>
+ <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
+ </Input>
+ </GridItem>
+ <GridItem>
+ <Input
+ className='entitlement-pools-form-row-threshold-value'
+ onChange={thresholdValue => onDataChanged({thresholdValue}, LKG_FORM_NAME,
+ {thresholdValue : thresholdValueValidation})}
+ label={i18n('Threshold Value')}
+ isValid={genericFieldInfo.thresholdValue.isValid}
+ errorText={genericFieldInfo.thresholdValue.errorText}
+ data-test-id='create-ep-threshold-value'
+ value={thresholdValue}
+ type='text'/>
+ </GridItem>
+ <GridItem>
+ <Input
+ type='date'
+ label={i18n('Start Date')}
+ value={startDate}
+ dateFormat={DATE_FORMAT}
+ startDate={startDate}
+ endDate={expiryDate}
+ onChange={startDate => onDataChanged(
+ {startDate: startDate ? startDate.format(DATE_FORMAT) : ''},
+ LKG_FORM_NAME,
+ {startDate: validateStartDate}
+ )}
+ isValid={genericFieldInfo.startDate.isValid}
+ errorText={genericFieldInfo.startDate.errorText}
+ selectsStart/>
+ </GridItem>
+ <GridItem>
+ <Input
+ type='date'
+ label={i18n('Expiry Date')}
+ value={expiryDate}
+ dateFormat={DATE_FORMAT}
+ startDate={startDate}
+ endDate={expiryDate}
+ onChange={expiryDate => {
+ onDataChanged({expiryDate: expiryDate ? expiryDate.format(DATE_FORMAT) : ''}, LKG_FORM_NAME);
+ onDataChanged({startDate}, LKG_FORM_NAME, {startDate: validateStartDate});
+ }}
+ isValid={genericFieldInfo.expiryDate.isValid}
+ errorText={genericFieldInfo.expiryDate.errorText}
+ selectsEnd/>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <Input
+ onChange={increments => onDataChanged({increments}, LKG_FORM_NAME)}
+ label={i18n('Increments')}
+ value={increments}
+ data-test-id='create-ep-increments'
+ type='text'/>
+ </GridItem>
</GridSection>
);
};
@@ -120,36 +210,100 @@ class LicenseKeyGroupsEditorView extends React.Component {
data: {}
};
+ componentDidUpdate(prevProps) {
+ if (this.props.formReady && this.props.formReady !== prevProps.formReady) { // if form validation succeeded -> continue with submit
+ this.submit();
+ }
+ }
+
+ state = {
+ localFeatureGroupsListFilter: '',
+ selectedTab: tabIds.GENERAL,
+ selectedLimit: ''
+ };
+
render() {
- let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo} = this.props;
+ let {data = {}, onDataChanged, isReadOnlyMode, onCloseLimitEditor, genericFieldInfo, limitsList = []} = this.props;
+ let {selectedTab} = this.state;
+ const isTabsDisabled = !data.id || !this.props.isFormValid;
return (
- <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'>
- <LicenseKeyGroupFormContent
- data={data}
- onDataChanged={onDataChanged}
- genericFieldInfo={genericFieldInfo}
- validateName={(value)=> this.validateName(value)}
- validateOperationalScope={this.validateOperationalScope}/>
- </Form>}
+ <div className='license-keygroup-editor'>
+ <Tabs
+ type='menu'
+ activeTab={selectedTab}
+ onTabClick={(tabIndex)=>{
+ if (tabIndex === tabIds.ADD_LIMIT_BUTTON) {
+ this.onAddLimit();
+ } else {
+ this.setState({selectedTab: tabIndex});
+ onCloseLimitEditor();
+ this.setState({selectedLimit: ''});
+ }
+ }}
+ invalidTabs={[]}>
+ <Tab tabId={tabIds.GENERAL} data-test-id='general-tab' title={i18n('General')}>
+ { genericFieldInfo &&
+ <Form
+ ref='validationForm'
+ hasButtons={false}
+ isValid={this.props.isFormValid}
+ formReady={this.props.formReady}
+ onValidateForm={() => this.props.onValidateForm(LKG_FORM_NAME) }
+ labledButtons={true}
+ isReadOnlyMode={isReadOnlyMode}
+ className='license-model-form license-key-groups-form'>
+ <LicenseKeyGroupFormContent
+ data={data}
+ onDataChanged={onDataChanged}
+ genericFieldInfo={genericFieldInfo}
+ validateName={(value)=> this.validateName(value)}
+ validateStartDate={(value, state)=> validateStartDate(value, state)}
+ thresholdValueValidation={(value, state) => thresholdValueValidation(value, state)}/>
+ </Form>}
+
+ </Tab>
+ <Tab tabId={tabIds.SP_LIMITS} disabled={isTabsDisabled} data-test-id='general-tab' title={i18n('SP Limits')}>
+ {selectedTab === tabIds.SP_LIMITS &&
+ <LicenseKeyGroupsLimits
+ limitType={limitType.SERVICE_PROVIDER}
+ limitsList={limitsList.filter(item => item.type === limitType.SERVICE_PROVIDER)}
+ selectedLimit={this.state.selectedLimit}
+ onCloseLimitEditor={() => this.onCloseLimitEditor()}
+ onSelectLimit={limit => this.onSelectLimit(limit)}/>}
+ </Tab>
+ <Tab tabId={tabIds.VENDOR_LIMITS} disabled={isTabsDisabled} data-test-id='general-tab' title={i18n('Vendor Limits')}>
+ {selectedTab === tabIds.VENDOR_LIMITS &&
+ <LicenseKeyGroupsLimits
+ limitType={limitType.VENDOR}
+ limitsList={limitsList.filter(item => item.type === limitType.VENDOR)}
+ selectedLimit={this.state.selectedLimit}
+ onCloseLimitEditor={() => this.onCloseLimitEditor()}
+ onSelectLimit={limit => this.onSelectLimit(limit)}/>}
+ </Tab>
+ {selectedTab !== tabIds.GENERAL ?
+ <Button disabled={this.state.selectedLimit} className='add-limit-button' tabId={tabIds.ADD_LIMIT_BUTTON} btnType='link' iconName='plus'>{i18n('Add Limit')}</Button> :
+ <div></div> // Render empty div to not break tabs
+ }
+ </Tabs>
+
+ <GridSection className='license-model-modal-buttons license-key-group-editor-buttons'>
+ {!this.state.selectedLimit && <Button btnType='default' disabled={!this.props.isFormValid} onClick={() => this.submit()} type='reset'>{i18n('Save')}</Button>}
+ <Button btnType={this.state.selectedLimit ? 'default' : 'outline'} onClick={() => this.props.onCancel()} type='reset'>
+ {i18n('Cancel')}
+ </Button>
+ </GridSection>
</div>
+
);
}
submit() {
- const {data: licenseKeyGroup, previousData: previousLicenseKeyGroup} = this.props;
- this.props.onSubmit({licenseKeyGroup, previousLicenseKeyGroup});
+ const {data: licenseKeyGroup, previousData: previousLicenseKeyGroup, formReady, onValidateForm, onSubmit} = this.props;
+ if (!formReady) {
+ onValidateForm(LKG_FORM_NAME);
+ } else {
+ onSubmit({licenseKeyGroup, previousLicenseKeyGroup});
+ }
}
validateName(value) {
@@ -160,27 +314,23 @@ class LicenseKeyGroupsEditorView extends React.Component {
{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: ''
- };
- }
- }
+ onSelectLimit(limit) {
+ if (limit.id === this.state.selectedLimit) {
+ this.setState({selectedLimit: ''});
+ return;
}
- return {
- isValid: false,
- errorText: 'Field is required'
- };
+ this.setState({selectedLimit: limit.id});
+ this.props.onOpenLimitEditor(limit);
+ }
+
+ onCloseLimitEditor() {
+ this.setState({selectedLimit: ''});
+ this.props.onCloseLimitEditor();
+ }
+
+ onAddLimit() {
+ this.setState({selectedLimit: NEW_LIMIT_TEMP_ID});
+ this.props.onOpenLimitEditor();
}
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsLimits.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsLimits.js
new file mode 100644
index 0000000000..7745a12fec
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsLimits.js
@@ -0,0 +1,57 @@
+/*!
+ * 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 i18n from 'nfvo-utils/i18n/i18n.js';
+import {actionTypes as globalModalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import Limits from 'sdc-app/onboarding/licenseModel/limits/Limits.jsx';
+
+import LicenseKeyGroupsActionHelper from './LicenseKeyGroupsActionHelper.js';
+
+const mapStateToProps = ({licenseModel: {licenseKeyGroup: {licenseKeyGroupsEditor: {data}}, limitEditor}, currentScreen}) => {
+ let {props: {licenseModelId, version}} = currentScreen;
+ return {
+ parent: data,
+ limitEditor,
+ licenseModelId,
+ version
+ };
+};
+
+const mapActionsToProps = (dispatch) => {
+ return {
+ onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
+ onSubmit: (limit, licenseKeyGroup, licenseModelId, version) => LicenseKeyGroupsActionHelper.submitLimit(dispatch,
+ {
+ limit,
+ licenseKeyGroup,
+ licenseModelId,
+ version}),
+ onDelete: ({limit, parent, licenseModelId, version, onCloseLimitEditor, selectedLimit}) => dispatch({
+ type: globalModalActionTypes.GLOBAL_MODAL_WARNING,
+ data:{
+ msg: i18n(`Are you sure you want to delete ${limit.name}?`),
+ confirmationButtonText: i18n('Delete'),
+ title: i18n('Warning'),
+ onConfirmed: ()=> LicenseKeyGroupsActionHelper.deleteLimit(dispatch, {limit, licenseKeyGroup: parent, licenseModelId, version}).then(() =>
+ selectedLimit === limit.id && onCloseLimitEditor()
+ )
+ }
+ })
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(Limits); \ No newline at end of file
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 e2c6c30e21..a8cf1eb0a1 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditor.js
@@ -38,7 +38,7 @@ const mapStateToProps = ({licenseModel: {licenseKeyGroup, licenseModelEditor}})
const mapActionsToProps = (dispatch, {licenseModelId, version}) => {
return {
onAddLicenseKeyGroupClick: () => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch),
- onEditLicenseKeyGroupClick: licenseKeyGroup => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch, {licenseKeyGroup}),
+ onEditLicenseKeyGroupClick: licenseKeyGroup => LicenseKeyGroupsActionHelper.openLicenseKeyGroupsEditor(dispatch, {licenseKeyGroup, licenseModelId, version}),
onDeleteLicenseKeyGroupClick: licenseKeyGroup => dispatch({
type: globalMoadlActions.GLOBAL_MODAL_WARNING,
data:{
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 b8ccd68bce..1a7f2b0b5b 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsListEditorView.jsx
@@ -21,7 +21,7 @@ import ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
import LicenseKeyGroupsEditor from './LicenseKeyGroupsEditor.js';
-import InputOptions, {other as optionInputOther} from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+import InputOptions, {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
import {optionsInputValues} from './LicenseKeyGroupsConstants';
class LicenseKeyGroupsListEditorView extends React.Component {
@@ -61,7 +61,7 @@ class LicenseKeyGroupsListEditorView extends React.Component {
isReadOnlyMode={isReadOnlyMode}>
{this.filterList().map(licenseKeyGroup => (this.renderLicenseKeyGroupListItem(licenseKeyGroup, isReadOnlyMode)))}
</ListEditorView>
- <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal license-key-groups-modal'>
+ <Modal show={isDisplayModal} bsSize='large' animation={true} className='onborading-modal license-model-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>
@@ -122,16 +122,20 @@ class LicenseKeyGroupsListEditorView extends React.Component {
}
getOperationalScopes(operationalScope) {
- if(operationalScope.choices.toString() === i18n(optionInputOther.OTHER) && operationalScope.other !== '') {
+
+ if(operationalScope.choices && operationalScope.choices.toString() === i18n(optionInputOther.OTHER)) {
return operationalScope.other;
}
- else {
+ else if (operationalScope.choices) {
let allOpScopes = '';
for (let opScope of operationalScope.choices) {
allOpScopes += allOpScopes === '' ? InputOptions.getTitleByName(optionsInputValues, opScope) : `, ${InputOptions.getTitleByName(optionsInputValues, opScope)}`;
}
return allOpScopes;
- }
+ }
+ else {
+ return '';
+ }
}
extractValue(item) {
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.js
new file mode 100644
index 0000000000..d483383472
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.js
@@ -0,0 +1,25 @@
+import {connect} from 'react-redux';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import LimitEditor from './LimitEditor.jsx';
+
+const mapStateToProps = ({licenseModel: {limitEditor}}) => {
+
+ let {data, genericFieldInfo, formReady} = limitEditor;
+ let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
+
+ return {
+ data,
+ genericFieldInfo,
+ isFormValid,
+ formReady
+ };
+};
+
+const mapActionsToProps = (dispatch) => {
+ return {
+ onDataChanged: (deltaData, formName, customValidations) => ValidationHelper.dataChanged(dispatch, {deltaData, formName, customValidations}),
+ onValidateForm: (formName) => ValidationHelper.validateForm(dispatch, formName)
+ };
+};
+
+export default connect(mapStateToProps, mapActionsToProps)(LimitEditor); \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.jsx
new file mode 100644
index 0000000000..f70f917725
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditor.jsx
@@ -0,0 +1,193 @@
+import React from 'react';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+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 {LIMITS_FORM_NAME, selectValues} from './LimitEditorConstants.js';
+import Button from 'sdc-ui/lib/react/Button.js';
+import Validator from 'nfvo-utils/Validator.js';
+
+const LimitPropType = React.PropTypes.shape({
+ id: React.PropTypes.string,
+ name: React.PropTypes.string,
+ description: React.PropTypes.string,
+ metric: React.PropTypes.string,
+ value: React.PropTypes.number,
+ aggregationFunction: React.PropTypes.string,
+ time: React.PropTypes.string,
+ unit: React.PropTypes.number
+});
+
+class LimitEditor extends React.Component {
+ static propTypes = {
+ data: LimitPropType,
+ limitsNames: React.PropTypes.object,
+ isReadOnlyMode: React.PropTypes.bool,
+ isFormValid: React.PropTypes.bool,
+ formReady: React.PropTypes.bool,
+ genericFieldInfo: React.PropTypes.object.isRequired,
+ onDataChanged: React.PropTypes.func.isRequired,
+ onSubmit: React.PropTypes.func.isRequired,
+ onValidateForm: React.PropTypes.func.isRequired,
+ onCancel: React.PropTypes.func.isRequired
+ };
+
+ componentDidUpdate(prevProps) {
+ if (this.props.formReady && this.props.formReady !== prevProps.formReady) {
+ this.submit();
+ }
+ }
+
+ render() {
+ let {data = {}, onDataChanged, isReadOnlyMode, genericFieldInfo, onCancel, isFormValid, formReady, onValidateForm} = this.props;
+ let {name, description, metric, value, aggregationFunction, time, unit} = data;
+ return (
+ <div className='limit-editor'>
+ {!data.id &&
+ <div className='limit-editor-title'>
+ {data.name ? data.name : i18n('NEW LIMIT')}
+ </div>}
+ {
+ genericFieldInfo &&
+ <Form
+ ref='validationForm'
+ hasButtons={false}
+ isValid={isFormValid}
+ formReady={formReady}
+ onValidateForm={() => onValidateForm(LIMITS_FORM_NAME) }
+ labledButtons={false}
+ isReadOnlyMode={isReadOnlyMode}
+ className='limit-editor-form'>
+ <GridSection className='limit-editor-form-grid-section'>
+ <GridItem colSpan={2}>
+ <Input
+ onChange={name => onDataChanged({name}, LIMITS_FORM_NAME, {name: () => this.validateName(name)})}
+ label={i18n('Name')}
+ data-test-id='limit-editor-name'
+ value={name}
+ isValid={genericFieldInfo.name.isValid}
+ errorText={genericFieldInfo.name.errorText}
+ isRequired={true}
+ type='text'/>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <Input
+ onChange={description => onDataChanged({description}, LIMITS_FORM_NAME)}
+ label={i18n('Description')}
+ data-test-id='limit-editor-description'
+ value={description}
+ isValid={genericFieldInfo.description.isValid}
+ errorText={genericFieldInfo.description.errorText}
+ isRequired={false}
+ type='text'/>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <Input
+ onChange={e => {
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onDataChanged({metric: val}, LIMITS_FORM_NAME);}
+ }
+ isRequired={true}
+ value={metric}
+ label={i18n('Metric')}
+ data-test-id='limit-editor-metric'
+ isValid={genericFieldInfo.metric.isValid}
+ errorText={genericFieldInfo.metric.errorText}
+ groupClassName='bootstrap-input-options'
+ className='input-options-select'
+ type='select' >
+ {selectValues.METRIC.map(mtype =>
+ <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
+ </Input>
+ </GridItem>
+ <GridItem>
+ <Input
+ onChange={value => onDataChanged({value}, LIMITS_FORM_NAME)}
+ label={i18n('Metric value')}
+ data-test-id='limit-editor-metric-value'
+ value={value}
+ isValid={genericFieldInfo.value.isValid}
+ errorText={genericFieldInfo.value.errorText}
+ isRequired={true}
+ type='number'/>
+ </GridItem>
+ <GridItem>
+ <Input
+ onChange={unit => onDataChanged({unit}, LIMITS_FORM_NAME)}
+ label={i18n('Units')}
+ data-test-id='limit-editor-units'
+ value={unit}
+ isValid={genericFieldInfo.unit.isValid}
+ errorText={genericFieldInfo.unit.errorText}
+ isRequired={false}
+ type='number'/>
+ </GridItem>
+ <GridItem colSpan={2}>
+ <Input
+ onChange={e => {
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onDataChanged({aggregationFunction: val}, LIMITS_FORM_NAME);}
+ }
+ value={aggregationFunction}
+ label={i18n('Aggregation Function')}
+ data-test-id='limit-editor-aggregation-function'
+ isValid={genericFieldInfo.aggregationFunction.isValid}
+ errorText={genericFieldInfo.aggregationFunction.errorText}
+ groupClassName='bootstrap-input-options'
+ className='input-options-select'
+ type='select' >
+ {selectValues.AGGREGATION_FUNCTION.map(mtype =>
+ <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
+ </Input>
+ </GridItem>
+ <GridItem>
+ <Input
+ onChange={e => {
+ const selectedIndex = e.target.selectedIndex;
+ const val = e.target.options[selectedIndex].value;
+ onDataChanged({time: val}, LIMITS_FORM_NAME);}
+ }
+ value={time}
+ label={i18n('Time')}
+ data-test-id='limit-editor-time'
+ isValid={genericFieldInfo.time.isValid}
+ errorText={genericFieldInfo.time.errorText}
+ groupClassName='bootstrap-input-options'
+ className='input-options-select'
+ type='select' >
+ {selectValues.TIME.map(mtype =>
+ <option key={mtype.enum} value={mtype.enum}>{`${mtype.title}`}</option>)}
+ </Input>
+ </GridItem>
+ </GridSection>
+ <GridSection className='limit-editor-buttons'>
+ <Button btnType='outline' disabled={!isFormValid} onClick={() => this.submit()} type='reset'>{i18n('Save')}</Button>
+ <Button btnType='outline' color='gray' onClick={onCancel} type='reset'>{i18n('Cancel')}</Button>
+ </GridSection>
+ </Form>
+ }
+ </div>
+ );
+ }
+
+ validateName(value) {
+ const {data: {id}, limitsNames} = this.props;
+ const isExists = Validator.isItemNameAlreadyExistsInList({itemId: id, itemName: value, list: limitsNames});
+
+ return !isExists ? {isValid: true, errorText: ''} :
+ {isValid: false, errorText: i18n('Limit by the name \'' + value + '\' already exists. Limit name must be unique')};
+ }
+
+ submit() {
+ if (!this.props.formReady) {
+ this.props.onValidateForm(LIMITS_FORM_NAME);
+ } else {
+ this.props.onSubmit();
+ }
+ }
+}
+
+export default LimitEditor; \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageNavigationReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorActionHelper.js
index 20d1f5dd18..09c64ada62 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageNavigationReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorActionHelper.js
@@ -13,20 +13,18 @@
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
-import {actionTypes} from './SoftwareProductComponentsImageConstants.js';
-export default (state = {}, action) => {
- switch (action.type) {
+import {actionTypes} from './LimitEditorConstants.js';
- case actionTypes.IMAGES_LIST_UPDATE:
- if (action.componentId) {
- return {
- ...state,
- [action.componentId] : (action.response && action.response.length > 0)
- };
- }
- return state;
- default:
- return state;
+
+const LimitEditorActionHelper = {
+ openLimitsEditor(dispatch, {limit}) {
+ dispatch({type: actionTypes.OPEN, limitItem: limit});
+ },
+
+ closeLimitsEditor(dispatch) {
+ dispatch({type: actionTypes.CLOSE});
}
};
+
+export default LimitEditorActionHelper; \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js
new file mode 100644
index 0000000000..1bef286442
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js
@@ -0,0 +1,52 @@
+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({
+ OPEN: null,
+ CLOSE: null,
+ DATA_CHANGED: null,
+});
+
+export const LIMITS_FORM_NAME = 'LIMITSFORM';
+
+export const selectValues = {
+ METRIC: [
+ {enum: '', title: i18n('please select…')},
+ {enum: 'Software_Instances_Count', title: 'Software Instances'},
+ {enum: 'Core', title: 'Core'},
+ {enum: 'CPU', title: 'CPU'},
+ {enum: 'Trunks', title: 'Trunks'},
+ {enum: 'User', title: 'User'},
+ {enum: 'Subscribers', title: 'Subscribers'},
+ {enum: 'Tenants', title: 'Tenants'},
+ {enum: 'Tokens', title: 'Tokens'},
+ {enum: 'Seats', title: 'Seats'},
+ {enum: 'Units_TB', title: 'Units-TB'},
+ {enum: 'Units_GB', title: 'Units-GB'},
+ {enum: 'Units_MB', title: 'Units-MB'}
+ ],
+ AGGREGATION_FUNCTION: [
+ {enum: '', title: i18n('please select…')},
+ {enum: 'Peak', title: 'Peak'},
+ {enum: 'Average', title: 'Average'}
+ ],
+ TIME: [
+ {enum: '', title: i18n('please select…')},
+ {enum: 'Hour', title: 'Hour'},
+ {enum: 'Day', title: 'Day'},
+ {enum: 'Month', title: 'Month'}
+ ]
+
+};
+
+export const limitType = {
+ SERVICE_PROVIDER: 'ServiceProvider',
+ VENDOR: 'Vendor'
+};
+
+export const defaultState = {
+ LIMITS_EDITOR_DATA: {}
+};
+
+export const NEW_LIMIT_TEMP_ID = 'NEW_LIMIT_TEMP_ID'; \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorReducer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorReducer.js
new file mode 100644
index 0000000000..2499093af2
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitEditorReducer.js
@@ -0,0 +1,70 @@
+/*!
+ * 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, LIMITS_FORM_NAME, defaultState} from './LimitEditorConstants.js';
+
+export default (state = {}, action) => {
+ switch (action.type) {
+ case actionTypes.OPEN:
+ return {
+ ...state,
+ data: action.limitItem ? {...action.limitItem} : defaultState.LIMITS_EDITOR_DATA,
+ formReady: null,
+ formName: LIMITS_FORM_NAME,
+ genericFieldInfo: {
+ 'description' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'maxLength', data: 1000}]
+ },
+ 'name' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'maxLength', data: 120}]
+ },
+ 'metric' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}]
+ },
+ 'value' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'required', data: true}, {type: 'numeric', data: true}, {type: 'minimum', data: 0}]
+ },
+ 'unit' : {
+ isValid: true,
+ errorText: '',
+ validations: [{type: 'numeric', data: true}]
+ },
+ 'aggregationFunction' : {
+ isValid: true,
+ errorText: '',
+ validations: []
+ },
+ 'time' : {
+ isValid: true,
+ errorText: '',
+ validations: []
+ }
+ }
+ };
+ case actionTypes.CLOSE:
+ return {};
+ default:
+ return state;
+ }
+}; \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/Limits.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/Limits.jsx
new file mode 100644
index 0000000000..ec5a1dff72
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/Limits.jsx
@@ -0,0 +1,108 @@
+/*!
+ * 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 ListEditorView from 'nfvo-components/listEditor/ListEditorView.jsx';
+import ListEditorItemView from 'nfvo-components/listEditor/ListEditorItemView.jsx';
+import LimitEditor from './LimitEditor.js';
+import {NEW_LIMIT_TEMP_ID, selectValues} from './LimitEditorConstants.js';
+
+const LimitItem = ({isReadOnlyMode, limit, onDelete, onSelect}) => {
+ const {name, description, metric, value, aggregationFunction = '', time = ''} = limit;
+ const timeLabel = time ? `per ${time}` : '';
+ return (
+ <ListEditorItemView
+ onDelete={onDelete}
+ onSelect={onSelect}
+ isReadOnlyMode={isReadOnlyMode}>
+ <div className='list-editor-item-view-field limit-name'>
+ <div className='text name'>{name}</div>
+ </div>
+
+ <div className='list-editor-item-view-field limit-description'>
+ <div className='text description'>{description}</div>
+ </div>
+
+ <div className='list-editor-item-view-field limit-metric-details'>
+ <div className='text description'>{`${selectValues.METRIC.find(item => item.enum === metric).title} ${value} ${aggregationFunction} ${timeLabel}`}</div>
+ </div>
+ </ListEditorItemView>
+ );
+};
+
+class Limits extends React.Component {
+
+
+ state = {
+ localFilter: ''
+ };
+
+ render() {
+ const {isReadOnlyMode = false, limitEditor, limitsList = [], onCloseLimitEditor, selectedLimit} = this.props;
+ let limitsNames = {};
+ for (let i = 0; i < limitsList.length; i++) {
+ limitsNames[limitsList[i].name.toLowerCase()] = limitsList[i].id;
+ }
+ return (
+ <div className='license-model-limits-view'>
+ <ListEditorView
+ isReadOnlyMode={isReadOnlyMode}>
+ {this.props.selectedLimit === NEW_LIMIT_TEMP_ID && limitEditor.data &&
+ <LimitEditor limitsNames={limitsNames} onCancel={onCloseLimitEditor} onSubmit={ () => this.submit()}/>
+ }
+ {limitsList.length === 0 && !limitEditor.data && <div className='no-limits-text'>{i18n('There are no limits')}</div>}
+ {limitsList.map(limit =>
+ <div key={limit.id} className='limit-item-wrapper'>
+ <LimitItem
+ onDelete={() => this.delete(limit)}
+ onSelect={selectedLimit ? undefined : () => this.props.onSelectLimit(limit)}
+ clickable={!selectedLimit}
+ isReadOnlyMode={isReadOnlyMode}
+ limit={limit}/>
+ {limit.id === selectedLimit && limitEditor.data && <LimitEditor limitsNames={limitsNames} onCancel={onCloseLimitEditor} onSubmit={ () => this.submit()}/>}
+ </div> )}
+ </ListEditorView>
+
+ </div>
+ );
+ }
+
+ submit() {
+ let {onSubmit, onCloseLimitEditor, parent, limitEditor, licenseModelId, version, limitType} = this.props;
+ onSubmit({type: limitType, ...limitEditor.data}, parent, licenseModelId, version).then(() => onCloseLimitEditor());
+ }
+
+ delete(limit) {
+ let {onDelete, parent, licenseModelId, version, onCloseLimitEditor, selectedLimit} = this.props;
+ onDelete({limit, parent, licenseModelId, version, onCloseLimitEditor, selectedLimit});
+ }
+
+ filterList() {
+ let {limitsList = []} = this.props;
+ let {localFilter} = this.state;
+ if (localFilter.trim()) {
+ const filter = new RegExp(escape(localFilter), 'i');
+ return limitsList.filter(({name = '', description = ''}) => {
+ return escape(name).match(filter) || escape(description).match(filter);
+ });
+ }
+ else {
+ return limitsList;
+ }
+ }
+}
+
+export default Limits;
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitsServer.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitsServer.js
new file mode 100644
index 0000000000..1b8ecb9d94
--- /dev/null
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/limits/LimitsServer.js
@@ -0,0 +1,46 @@
+/*!
+ * 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.
+ */
+
+// items/{itemId}/users
+
+let list = [
+
+];
+
+export default {
+ fetch() {
+ return Promise.resolve({
+ listCount: list.length,
+ results: list
+ });
+ },
+
+ put(url, payload) {
+ // let {removedUsers, addedUsers} = payload;
+ // users = users.filter(user => !removedUsers.map(user => user.userId).includes(user.userId)).concat(addedUsers);
+ payload.id = Math.random() * (1000 - 1) + 1;
+ list.push(payload);
+ return Promise.resolve();
+ },
+
+ destroy(url) {
+ const parts = url.split('/');
+ const id = parts[parts.length - 1];
+ let newList = list.filter(item => item.id !== id);
+ list = newList;
+ return Promise.resolve();
+ }
+}; \ No newline at end of file
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js
index b5a27ed018..56b23384a7 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewConstants.js
@@ -34,9 +34,9 @@ export const actionTypes = keyMirror({
LM_DATA_CHANGED: null
});
-export const selectedButton = keyMirror({
- VLM_LIST_VIEW: null,
- NOT_IN_USE: null
-});
+export const selectedButton = {
+ VLM_LIST_VIEW: 'VLM_LIST_VIEW',
+ NOT_IN_USE: 'NOT_IN_USE'
+};
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
index d6c79ddb52..15f6c2d1bb 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/LicenseModelOverviewView.jsx
@@ -52,7 +52,7 @@ class LicenseModelOverviewView extends React.Component {
licenseModelId: React.PropTypes.string,
licensingDataList: React.PropTypes.array,
modalHeader: React.PropTypes.string,
- selectedTab: React.PropTypes.symbol,
+ selectedTab: React.PropTypes.string,
onTabSelect: React.PropTypes.func,
onCallVCAction: React.PropTypes.func,
onClose: React.PropTypes.func
@@ -67,14 +67,13 @@ class LicenseModelOverviewView extends React.Component {
<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}/>
+ <ListButtons onTabSelect={onTabSelect} selectedTab={selectedTab}/>
</div>
<VLMListView licensingDataList={licensingDataList} showInUse={selectedInUse}/>
</div>
{
isDisplayModal &&
- <Modal show={isDisplayModal} bsSize='large' animation={true} className={classNames('onborading-modal', setModalClassName(modalHeader))}>
+ <Modal show={isDisplayModal} bsSize='large' animation={true} className={classNames('onborading-modal license-model-modal', setModalClassName(modalHeader))}>
<Modal.Header>
<Modal.Title>{`${i18n('Create New ')}${i18n(modalHeader)}`}</Modal.Title>
</Modal.Header>
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx
index 119008a849..ec05e37681 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/VLMListView.jsx
@@ -66,7 +66,8 @@ class VLMListView extends Component {
<LicenseAgreement
laData={licenseAgreement}
isCollapsed={this.state[licenseAgreement.id]}
- onClick={event => this.updateCollapsable(event, licenseAgreement.id) }/>
+ onClick={event => this.updateCollapsable(event, licenseAgreement.id) }
+ isOrphan={!this.props.showInUse}/>
<Collapse in={this.state[licenseAgreement.id]}>
<ul>
{licenseAgreement.children && licenseAgreement.children.map(item => this.renderLicensingItem(item))}
@@ -83,7 +84,8 @@ class VLMListView extends Component {
<FeatureGroup
fgData={featureGroup}
isCollapsed={this.state[featureGroup.id]}
- onClick={event=> this.updateCollapsable(event, featureGroup.id) }/>
+ onClick={event=> this.updateCollapsable(event, featureGroup.id) }
+ isOrphan={!this.props.showInUse}/>
{
showInUse && <Collapse in={this.state[featureGroup.id]}>
<ul>
@@ -99,7 +101,7 @@ class VLMListView extends Component {
renderEntitlementPoolItem(entitlementPool) {
return (
<li key={entitlementPool.id}>
- <EntitlementPool epData={entitlementPool} />
+ <EntitlementPool epData={entitlementPool} isOrphan={!this.props.showInUse}/>
</li>
);
}
@@ -107,7 +109,7 @@ class VLMListView extends Component {
renderLicenseKeyGroupItem(licenseKeyGroup) {
return (
<li key={licenseKeyGroup.id}>
- <LicenseKeyGroup lkgData={licenseKeyGroup} />
+ <LicenseKeyGroup lkgData={licenseKeyGroup} isOrphan={!this.props.showInUse}/>
</li>
);
}
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
index 94977b40d1..34d2ee6db5 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/EntitlementPool.jsx
@@ -15,7 +15,7 @@
*/
import React, {Component} from 'react';
import i18n from 'nfvo-utils/i18n/i18n.js';
-import {extractValue, extractUnits} from '../../entitlementPools/EntitlementPoolsConstants.js';
+import {extractUnits} from '../../entitlementPools/EntitlementPoolsConstants.js';
import ArrowCol from './listItemsComponents/ArrowCol.jsx';
import ItemInfo from './listItemsComponents/ItemInfo.jsx';
import IconCol from './listItemsComponents/IconCol.jsx';
@@ -23,31 +23,23 @@ import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/Ad
class EntitlementPool extends Component {
render() {
- let {epData: {name, description, manufacturerReferenceNumber}} = this.props;
+ let {epData: {name, description, thresholdValue, thresholdUnits}, isOrphan} = this.props;
return (
- <div className='vlm-list-item vlm-list-item-ep' data-test-id='vlm-list-item-ep'>
- <ArrowCol/>
- <IconCol className='ep-icon'/>
+ <div className={`vlm-list-item vlm-list-item-ep ${isOrphan ? 'orphan-list-item' : ''}`} data-test-id='vlm-list-item-ep'>
+ {!isOrphan && <ArrowCol/>}
+ <IconCol className='ep-icon' text='EP'/>
<ItemInfo name={name} description={description}/>
<AdditionalDataCol>
- <AdditionalDataElement
+ {thresholdValue && <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'/>
+ value={`${thresholdValue} ${extractUnits(thresholdUnits)}`}/>
+ }
</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
index 8dbd46a29e..6d97dea358 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/FeatureGroup.jsx
@@ -18,30 +18,41 @@ import {overviewEditorHeaders} from '../LicenseModelOverviewConstants.js';
import ArrowCol from './listItemsComponents/ArrowCol.jsx';
import ItemInfo from './listItemsComponents/ItemInfo.jsx';
import IconCol from './listItemsComponents/IconCol.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/AdditionalDataCol.jsx';
class FeatureGroup extends Component {
render() {
- let {fgData: {name, description, children = []}, isCollapsed, onClick} = this.props;
+ let {fgData: {name, manufacturerReferenceNumber, description, children = []}, isCollapsed, onClick, isOrphan} = 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'/>
+ <div
+ onClick={e => onClick(e)}
+ className={`vlm-list-item vlm-list-item-fg ${isOrphan ? 'orphan-list-item' : ''} ${children.length && !isOrphan ? 'clickable' : ''}`} data-test-id='vlm-list-item-fg'>
+ {!isOrphan && <ArrowCol isCollapsed={isCollapsed} length={children.length} />}
+ <IconCol className='fg-icon' text='FG'/>
<ItemInfo name={name} description={description}>
<div className='children-count'>
<span className='count-value'>
- Entitlement Pools:
+ {i18n('Entitlement Pools: ')}
<span data-test-id='vlm-list-ep-count-value'>
{`${children.filter(child => child.itemType === overviewEditorHeaders.ENTITLEMENT_POOL).length}`}
</span>
</span>
+ <span className='fg-pipeline-separator'>|</span>
<span className='count-value'>
- License Key Groups:
+ {i18n('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>
+ <AdditionalDataCol>
+ <AdditionalDataElement
+ name={i18n('Manufacturer Reference Number')}
+ value={manufacturerReferenceNumber}
+ className='vlm-list-item-sku'/>
+ </AdditionalDataCol>
</div>
);
}
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
index dd4686d330..dfbbe20d69 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseAgreement.jsx
@@ -15,7 +15,7 @@
*/
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 InputOptions, {other as optionInputOther} from 'nfvo-components/input/validation/InputOptions.jsx';
import {optionsInputValues} from '../../licenseAgreement/LicenseAgreementConstants.js';
import ArrowCol from './listItemsComponents/ArrowCol.jsx';
import ItemInfo from './listItemsComponents/ItemInfo.jsx';
@@ -24,14 +24,17 @@ import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/Ad
class LicenseAgreement extends Component {
render() {
- let {laData: {name, description, licenseTerm, children = []}, isCollapsed, onClick} = this.props;
+ let {laData: {name, description, licenseTerm, children = []}, isCollapsed, onClick, isOrphan} = 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'/>
+ <div
+ onClick={e => onClick(e)}
+ className={`vlm-list-item vlm-list-item-la ${isOrphan ? 'orphan-list-item' : ''} ${children.length && !isOrphan ? 'clickable' : ''} `}
+ data-test-id='vlm-list-la-item'>
+ {!isOrphan && <ArrowCol isCollapsed={isCollapsed} length={children.length} />}
+ <IconCol className='la-icon' text='LA'/>
<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>
+ <span className='count-value'>{i18n('Feature Groups: ')}<span data-test-id='vlm-list-fg-count-value'>{`${children.length}`}</span></span>
</div>
</ItemInfo>
<AdditionalDataCol>
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
index 9722b83336..b1036aae23 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/listItems/LicenseKeyGroup.jsx
@@ -23,17 +23,17 @@ import {AdditionalDataCol, AdditionalDataElement} from './listItemsComponents/Ad
class LicenseKeyGroup extends Component {
render() {
- let {lkgData: {name, description, operationalScope, type}} = this.props;
+ let {lkgData: {name, description, operationalScope, type}, isOrphan} = this.props;
return (
- <div className='vlm-list-item vlm-list-item-lkg' data-test-id='vlm-list-item-lkg'>
- <ArrowCol/>
- <IconCol className='lkg-icon'/>
+ <div className={`vlm-list-item vlm-list-item-lkg ${isOrphan ? 'orphan-list-item' : ''}`} data-test-id='vlm-list-item-lkg'>
+ {!isOrphan && <ArrowCol/>}
+ <IconCol className='lkg-icon' text='LKG'/>
<ItemInfo name={name} description={description}/>
<AdditionalDataCol>
- <AdditionalDataElement
+ {operationalScope && operationalScope.choices && <AdditionalDataElement
className='vlm-list-item-operational-scope'
name={i18n('Operational Scope')}
- value={operationalScope && getOperationalScopes(operationalScope)}/>
+ value={getOperationalScopes(operationalScope)}/>}
<AdditionalDataElement
className='vlm-list-item-group-type'
name={i18n('Type')}
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
index 7fd7fcb88a..826248e510 100644
--- 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
@@ -15,10 +15,10 @@
*/
import React from 'react';
-function IconCol({className}) {
+function IconCol({className, text}) {
return (
<div className='list-item-section list-item-icon-col'>
- <div className={className}></div>
+ <div className={`overview-list-icon ${className ? className : ''}`}>{text}</div>
</div>
);
}
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
index 730ccb33f1..3d81aa5d5c 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/ListButtons.jsx
@@ -15,19 +15,26 @@
*/
import React from 'react';
import {selectedButton} from '../LicenseModelOverviewConstants.js';
+import Tabs from 'sdc-ui/lib/react/Tabs.js';
+import Tab from 'sdc-ui/lib/react/Tab.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
-function ListButtons ({onTabSelect, selectedInUse}) {
+function ListButtons ({onTabSelect, selectedTab}) {
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>
+ <Tabs
+ onTabClick={(tabId) => onTabSelect(tabId)}
+ activeTab={selectedTab}
+ className='overview-buttons-section'
+ type='header' >
+ <Tab
+ tabId={selectedButton.VLM_LIST_VIEW}
+ title={i18n('Connections List')}
+ data-test-id='vlm-overview-vlmlist-tab' />
+ <Tab
+ tabId={selectedButton.NOT_IN_USE}
+ title={i18n('Orphans List')}
+ data-test-id='vlm-overview-orphans-tab' />
+ </Tabs>
);
}
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
index 1d65ab9869..87559901b3 100644
--- a/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js
+++ b/openecomp-ui/src/sdc-app/onboarding/licenseModel/overview/summary/VendorDataView.js
@@ -13,9 +13,11 @@
* or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
-import React from 'react';
+import React, {Component} from 'react';
import {connect} from 'react-redux';
+import Tooltip from 'react-bootstrap/lib/Tooltip.js';
+import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger.js';
import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
import licenseModelOverviewActionHelper from '../licenseModelOverviewActionHelper.js';
import LicenseModelActionHelper from '../../LicenseModelActionHelper.js';
@@ -46,9 +48,7 @@ const mapActionsToProps = (dispatch) => {
};
};
-
-
-export class VendorDataView extends React.Component {
+export class VendorDataView extends Component {
render() {
let {data: {vendorName}, description, isReadOnlyMode} = this.props;
return (
@@ -62,13 +62,16 @@ export class VendorDataView extends React.Component {
);
}
+
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 onClick={() => {if (!isReadOnlyMode) {onVendorDescriptionEdit(description);}}} className={!isReadOnlyMode ? 'vendor-description' : 'vendor-description-readonly'}>
+ {this.renderOverlay(
+ <div className='description-data' data-test-id='vlm-summary-vendor-description'>
+ {description}
+ </div>
+ )}
</div>
);
}
@@ -80,7 +83,21 @@ export class VendorDataView extends React.Component {
);
}
+ renderOverlay(children) {
+ let {data: {description}, isReadOnlyMode} = this.props;
+ if (isReadOnlyMode) {
+ return (
+ <OverlayTrigger
+ placement='bottom'
+ overlay={<Tooltip className='vendor-description-tooltip' id='tooltip-bottom'>{description}</Tooltip>}
+ delayShow={400}>
+ {children}
+ </OverlayTrigger>
+ );
+ }
+ return children;
+ }
+
}
export default connect(mapStateToProps, mapActionsToProps)(VendorDataView);
-
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx
index 3b3e2fcf40..5939499ec5 100644
--- a/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.jsx
@@ -49,7 +49,7 @@ const CatalogTileVendorName = ({vendorName, catalogItemTypeClass}) => {
};
const CatalogTileItemName = ({name}) => (
- <OverlayTrigger placement='top' overlay={tooltip(name && name.toUpperCase())}>
+ <OverlayTrigger placement='top' overlay={tooltip(name)}>
<div className='catalog-tile-item-name'>{name}</div>
</OverlayTrigger>
);
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js
index 07d6c740e0..c9c95f359e 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js
@@ -36,7 +36,7 @@ function getActiveNavigationId(screen, componentId) {
return activeItemId;
}
-const buildComponentNavigationBarGroups = ({componentId, meta, hasImages}) => {
+const buildComponentNavigationBarGroups = ({componentId, meta}) => {
const groups = ([
{
id: navigationItems.GENERAL + '|' + componentId,
@@ -67,7 +67,6 @@ const buildComponentNavigationBarGroups = ({componentId, meta, hasImages}) => {
id: navigationItems.IMAGES + '|' + componentId,
name: i18n('Images'),
disabled: false,
- hidden: (!hasImages),
meta
}, {
id: navigationItems.PROCESS_DETAILS + '|' + componentId,
@@ -85,7 +84,7 @@ const buildComponentNavigationBarGroups = ({componentId, meta, hasImages}) => {
return groups;
};
-const buildNavigationBarProps = ({softwareProduct, meta, screen, componentId, componentsList, mapOfExpandedIds, imagesNavigationList}) => {
+const buildNavigationBarProps = ({softwareProduct, meta, screen, componentId, componentsList, mapOfExpandedIds}) => {
const {softwareProductEditor: {data: currentSoftwareProduct = {}}} = softwareProduct;
const {id, name, onboardingMethod} = currentSoftwareProduct;
const groups = [{
@@ -148,8 +147,7 @@ const buildNavigationBarProps = ({softwareProduct, meta, screen, componentId, co
name: displayName,
meta,
expanded: mapOfExpandedIds[navigationItems.COMPONENTS + '|' + id] === true && screen !== enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
- items: buildComponentNavigationBarGroups({componentId: id, meta,
- hasImages : (onboardingMethod === onboardingMethodTypes.MANUAL || imagesNavigationList[id] === true)})
+ items: buildComponentNavigationBarGroups({componentId: id, meta})
}))
]
}
@@ -193,12 +191,12 @@ function buildMeta({softwareProduct, componentId, softwareProductDependencies})
const mapStateToProps = ({softwareProduct}, {currentScreen: {screen, props: {componentId}}}) => {
const {softwareProductEditor, softwareProductComponents, softwareProductDependencies} = softwareProduct;
const {mapOfExpandedIds = []} = softwareProductEditor;
- const {componentsList = [], images: {imagesNavigationList}} = softwareProductComponents;
+ const {componentsList = []} = softwareProductComponents;
const meta = buildMeta({softwareProduct, componentId, softwareProductDependencies});
return {
versionControllerProps: buildVersionControllerProps(softwareProduct),
- navigationBarProps: buildNavigationBarProps({softwareProduct, meta, screen, componentId, componentsList, mapOfExpandedIds, imagesNavigationList}),
+ navigationBarProps: buildNavigationBarProps({softwareProduct, meta, screen, componentId, componentsList, mapOfExpandedIds}),
meta
};
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js
index d6ba86ad6e..90a2bb8f2e 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js
@@ -251,8 +251,7 @@ const SoftwareProductActionHelper = {
processAndValidateHeatCandidate(dispatch, {softwareProductId, version}){
return validateHeatCandidate(softwareProductId, version).then(response => {
if (response.status === 'Success') {
- let isFetchImageDetails = true;
- SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version, isFetchImageDetails});
+ SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(dispatch, {softwareProductId, version});
SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {softwareProductId, version});
}
});
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js
index 5248c4e8fd..977a76ac69 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductReducer.js
@@ -35,7 +35,6 @@ import SoftwareProductComponentsNICListReducer from './components/network/Softwa
import SoftwareProductComponentsNICEditorReducer from './components/network/SoftwareProductComponentsNICEditorReducer.js';
import SoftwareProductComponentsImageListReducer from './components/images/SoftwareProductComponentsImageListReducer.js';
import SoftwareProductComponentsImageEditorReducer from './components/images/SoftwareProductComponentsImageEditorReducer.js';
-import SoftwareProductComponentsImageNavigationReducer from './components/images/SoftwareProductComponentsImageNavigationReducer.js';
import SoftwareProductComponentsNICCreationReducer from './components/network/NICCreation/NICCreationReducer.js';
import SoftwareProductComponentsMonitoringReducer from './components/monitoring/SoftwareProductComponentsMonitoringReducer.js';
import SoftwareProductComponentsComputeFlavorListReducer from './components/compute/computeComponents/computeFlavor/ComputeFlavorListReducer.js';
@@ -83,7 +82,6 @@ export default combineReducers({
}),
images: combineReducers({
imagesList: SoftwareProductComponentsImageListReducer,
- imagesNavigationList: SoftwareProductComponentsImageNavigationReducer,
imageEditor: createPlainDataReducer(createComposedJSONSchemaReducer(IMAGE_QUESTIONNAIRE, SoftwareProductComponentsImageEditorReducer))
}),
computeFlavor: combineReducers({
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js
index 53143647a3..87953bb8aa 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/setup/HeatSetupActionHelper.js
@@ -17,8 +17,8 @@ import {actionTypes} from './HeatSetupConstants.js';
import isEqual from 'lodash/isEqual.js';
import cloneDeep from 'lodash/cloneDeep.js';
import SoftwareProductActionHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
+// import i18n from 'nfvo-utils/i18n/i18n.js';
+// import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
export default {
@@ -56,7 +56,11 @@ export default {
dispatch({type: actionTypes.ADD_ALL_UNASSIGNED_TO_ARTIFACTS});
},
- heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) {
+ heatSetupLeaveConfirmation() {
+ return Promise.resolve();
+ }
+
+ /*heatSetupLeaveConfirmation(dispatch, {softwareProductId, heatSetup, heatSetupCache}) {
return new Promise((resolve, reject) => {
if (isEqual({...heatSetup, softwareProductId}, heatSetupCache)) {
resolve();
@@ -73,5 +77,5 @@ export default {
});
}
});
- }
+ }*/
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js
index 71dc8325ad..8085c875f4 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/SoftwareProductComponentsActionHelper.js
@@ -18,7 +18,6 @@ import Configuration from 'sdc-app/config/Configuration.js';
import {actionTypes, COMPONENTS_QUESTIONNAIRE} from './SoftwareProductComponentsConstants.js';
import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
-import SoftwareProductComponentsImageActionHelper from './images/SoftwareProductComponentsImageActionHelper.js';
import {actionTypes as modalActionTypes} from 'nfvo-components/modal/GlobalModalConstants.js';
function baseUrl(softwareProductId, version) {
@@ -69,32 +68,12 @@ function postSoftwareProductComponent(softwareProductId, vspComponent, version)
const SoftwareProductComponentsActionHelper = {
- fetchSoftwareProductComponents(dispatch, {softwareProductId, version, isFetchImageDetails = false}) {
+ fetchSoftwareProductComponents(dispatch, {softwareProductId, version}) {
return fetchSoftwareProductComponents(softwareProductId, version).then(response => {
- let componentImagesCalls = [];
- if (isFetchImageDetails && response.listCount) {
- response.results.map(component => {
- let componentId = component.id;
- componentImagesCalls[componentImagesCalls.length] =
- SoftwareProductComponentsImageActionHelper.fetchImagesList(dispatch, {
- softwareProductId,
- componentId,
- version
- });
-
- });
- return Promise.all(componentImagesCalls).then(() => {
- dispatch({
- type: actionTypes.COMPONENTS_LIST_UPDATE,
- componentsList: response.results
- });
- });
- } else {
- dispatch({
- type: actionTypes.COMPONENTS_LIST_UPDATE,
- componentsList: response.results
- });
- }
+ dispatch({
+ type: actionTypes.COMPONENTS_LIST_UPDATE,
+ componentsList: response.results
+ });
});
},
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js
index 86c4e072d4..fb3bd35eb2 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageList.js
@@ -77,9 +77,10 @@ const mapActionsToProps = (dispatch, {softwareProductId, componentId}) => {
image, isReadOnlyMode, softwareProductId, componentId, version, modalClassName: 'image-modal-edit'}
);
},
- onSubmit: ({qdata}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch,
+ onSubmit: (version, qdata) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponentQuestionnaire(dispatch,
{softwareProductId,
vspComponentId: componentId,
+ version,
qdata});
}
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx
index ccf5b9d6b1..54def08fc1 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/images/SoftwareProductComponentsImageListView.jsx
@@ -125,8 +125,8 @@ class SoftwareProductComponentsImageListView extends React.Component {
}
save() {
- let {onSubmit, qdata} = this.props;
- return onSubmit({qdata});
+ let {onSubmit, qdata, version} = this.props;
+ return onSubmit(version, qdata);
}
}
export default SoftwareProductComponentsImageListView;
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx
index 2ad48ec84b..36c1728ef3 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/monitoring/SoftwareProductComponentsMonitoringView.jsx
@@ -96,7 +96,7 @@ class SoftwareProductComponentsMonitoringView extends Component {
<ButtonToolbar>
<ButtonGroup>
<Button disabled>{filename}</Button>
- <Button className='delete-button' onClick={()=>this.props.onDeleteFile(type)}>X</Button>
+ <Button data-test-id={`monitoring-delete-${type}`} className='delete-button' onClick={()=>this.props.onDeleteFile(type)}>X</Button>
</ButtonGroup>
</ButtonToolbar>
);
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx
index 5a159b4a87..4d460c722d 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/network/SoftwareProductComponentsNetworkListView.jsx
@@ -122,7 +122,7 @@ class SoftwareProductComponentsNetworkView extends React.Component {
<ListEditorItemViewField>
<div className={isManual ? 'details-col' : 'details'}>
<div className={isManual ? 'manual-title' : 'title'}>{i18n('Purpose of NIC')}</div>
- <div className={isManual ? 'description' : ''}>{description ? description : i18n('N/A')}</div>
+ {description && <div className={isManual ? 'description' : ''}>{description}</div>}
</div>
{!isManual && <div className='details'>
<div className='title'>{i18n('Network')}</div>
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js
index 18a3b1e8ff..7149adbbfb 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorage.js
@@ -33,14 +33,15 @@ const mapStateToProps = ({softwareProduct}) => {
qdata,
isReadOnlyMode,
qGenericFieldInfo,
- dataMap
+ dataMap,
+ version: currentVSP.version
};
};
-const mapActionToProps = (dispatch, {softwareProductId, version, componentId}) => {
+const mapActionToProps = (dispatch, {softwareProductId, componentId}) => {
return {
onQDataChanged: (deltaData) => ValidationHelper.qDataChanged(dispatch, {deltaData, qName: COMPONENTS_QUESTIONNAIRE}),
- onSubmit: ({componentData, qdata}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(dispatch,
+ onSubmit: ({componentData, qdata, version}) => { return SoftwareProductComponentsActionHelper.updateSoftwareProductComponent(dispatch,
{softwareProductId, version, vspComponentId: componentId, componentData, qdata});
}
};
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx
index 28bdf8e5e5..00df21bb59 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/components/storage/SoftwareProductComponentStorageView.jsx
@@ -162,7 +162,7 @@ class SoftwareProductComponentStorageView extends React.Component {
};
render() {
- let {onQDataChanged, dataMap, qGenericFieldInfo, isReadOnlyMode, onSubmit, qdata} = this.props;
+ let {onQDataChanged, dataMap, qGenericFieldInfo, isReadOnlyMode, onSubmit, qdata, version} = this.props;
return(
<div className='vsp-component-questionnaire-view'>
@@ -170,7 +170,7 @@ class SoftwareProductComponentStorageView extends React.Component {
ref={form => this.form = form }
isValid={true}
formReady={null}
- onSubmit={() => onSubmit({qdata})}
+ onSubmit={() => onSubmit({qdata, version})}
className='component-questionnaire-validation-form'
isReadOnlyMode={isReadOnlyMode}
hasButtons={false}>
@@ -182,8 +182,9 @@ class SoftwareProductComponentStorageView extends React.Component {
);
}
- save(){
- return this.form.handleFormSubmit(new Event('dummy'));
+ save(){
+ const {componentData, qdata, onSubmit, version} = this.props;
+ return onSubmit({componentData, qdata, version});
}
}
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js
index 19e2d5b0db..3b973c65cd 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js
@@ -27,7 +27,7 @@ export const mapStateToProps = ({finalizedLicenseModelList, softwareProductList,
let VSPNames = {};
for (let i = 0; i < softwareProductList.length; i++) {
- VSPNames[softwareProductList[i].name] = softwareProductList[i].id;
+ VSPNames[softwareProductList[i].name.toLowerCase()] = softwareProductList[i].id;
}
return {
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx
index 2e0cd340de..a427470a4f 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/dependencies/SoftwareProductDependenciesView.jsx
@@ -63,14 +63,15 @@ export default class SoftwareProductDependenciesView extends React.Component {
numOfIcons={2}
isReadOnlyMode={isReadOnlyMode}
onAdd={canAdd ? onAddDependency : undefined}
- onAddItem={i18n('Add Rule')}>
+ onAddItem={i18n('Add Rule')}>
{softwareProductDependencies.map(dependency => (
<SelectActionTableRow
key={dependency.id}
onDelete={() => onDataChanged(softwareProductDependencies.filter(currentDependency => currentDependency.id !== dependency.id))}
overlayMsg={i18n('There is a loop between selections')}
hasError={dependency.hasCycle}
- hasErrorIndication>
+ hasErrorIndication
+ showDelete={dependency.id !== 'fake' || dependency.hasCycle !== undefined}>
<SelectActionTableCell
options={this.filterSources({componentsOptions, sourceToTargetMapping, selectedSourceId: dependency.sourceId, selectedTargetId: dependency.targetId})}
selected={dependency.sourceId}
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditor.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditor.js
index 6b924a2816..ba00d4e56e 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditor.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/deployment/editor/SoftwareProductDeploymentEditor.js
@@ -58,7 +58,7 @@ export function mapStateToProps({licenseModel, softwareProduct}) {
let DFNames = {};
deploymentFlavors.map(deployment => {
- DFNames[deployment.model] = deployment.id;
+ DFNames[deployment.model.toLowerCase()] = deployment.id;
});
return {
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx
index 98dd7730bd..e4caf92c21 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/details/SoftwareProductDetailsView.jsx
@@ -19,7 +19,7 @@ import i18n from 'nfvo-utils/i18n/i18n.js';
import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
import Form from 'nfvo-components/input/validation/Form.jsx';
import Input from 'nfvo-components/input/validation/Input.jsx';
-import InputOptions from 'nfvo-components/input/inputOptions/InputOptions.jsx';
+import InputOptions from 'nfvo-components/input/validation/InputOptions.jsx';
import GridSection from 'nfvo-components/grid/GridSection.jsx';
import GridItem from 'nfvo-components/grid/GridItem.jsx';
import SoftwareProductCategoriesHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js';
diff --git a/openecomp-ui/test-utils/factories/licenseModel/EntitlementPoolFactories.js b/openecomp-ui/test-utils/factories/licenseModel/EntitlementPoolFactories.js
index 14df58e4c2..a28245e8bc 100644
--- a/openecomp-ui/test-utils/factories/licenseModel/EntitlementPoolFactories.js
+++ b/openecomp-ui/test-utils/factories/licenseModel/EntitlementPoolFactories.js
@@ -19,9 +19,7 @@ import {overviewEditorHeaders} from 'sdc-app/onboarding/licenseModel/overview/Li
Factory.define('EntitlementPoolBaseFactory')
.attrs({
name: 'EntitlementPoolName',
- description: 'description',
- entitlementMetric: {'choice': 'User', 'other': ''},
- manufacturerReferenceNumber: '123'
+ description: 'description'
});
Factory.define('EntitlementPoolExtendedBaseFactory')
@@ -29,10 +27,10 @@ Factory.define('EntitlementPoolExtendedBaseFactory')
.attrs({
thresholdValue: 75,
thresholdUnits: '%',
- increments: 'string',
- aggregationFunction: {'choice': 'Average', 'other': ''},
- operationalScope: {'choices': ['Other'], 'other': 'blabla'},
- time: {'choice': 'Hour', 'other': ''}
+ increments: 'string',
+ operationalScope: {'choices': ['Other'], 'other': 'blabla'},
+ startDate: (new Date()).getTime(),
+ expiryDate: (new Date()).getTime()
});
export const EntitlementPoolListItemFactory = new Factory()
diff --git a/openecomp-ui/test-utils/factories/licenseModel/LimitFactories.js b/openecomp-ui/test-utils/factories/licenseModel/LimitFactories.js
new file mode 100644
index 0000000000..a08e7e6355
--- /dev/null
+++ b/openecomp-ui/test-utils/factories/licenseModel/LimitFactories.js
@@ -0,0 +1,38 @@
+/*!
+ * 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 {Factory} from 'rosie';
+import {limitType} from 'sdc-app/onboarding/licenseModel/limits/LimitEditorConstants.js';
+import IdMixin from 'test-utils/factories/mixins/IdMixin.js';
+
+Factory.define('LimitBaseFactory')
+ .attrs({
+ name: 'SpLimit1',
+ type: limitType.SERVICE_PROVIDER,
+ description: 'fgfg',
+ metric: 'CPU',
+ value: 45,
+ unit: 55,
+ aggregationFunction: 'Peak',
+ time: 'Day'
+ });
+
+export const LimitPostFactory = new Factory()
+ .extend('LimitBaseFactory');
+
+export const LimitItemFactory = new Factory()
+ .extend('LimitBaseFactory')
+ .extend(IdMixin);
diff --git a/openecomp-ui/test/licenseModel/entitlementPools/test.js b/openecomp-ui/test/licenseModel/entitlementPools/test.js
index 15e1deecd6..911fb011f4 100644
--- a/openecomp-ui/test/licenseModel/entitlementPools/test.js
+++ b/openecomp-ui/test/licenseModel/entitlementPools/test.js
@@ -20,6 +20,7 @@ import {storeCreator} from 'sdc-app/AppStore.js';
import EntitlementPoolsActionHelper from 'sdc-app/onboarding/licenseModel/entitlementPools/EntitlementPoolsActionHelper.js';
import {EntitlementPoolStoreFactory, EntitlementPoolPostFactory} from 'test-utils/factories/licenseModel/EntitlementPoolFactories.js';
import VersionControllerUtilsFactory from 'test-utils/factories/softwareProduct/VersionControllerUtilsFactory.js';
+import {LimitItemFactory, LimitPostFactory} from 'test-utils/factories/licenseModel/LimitFactories.js';
describe('Entitlement Pools Module Tests', function () {
@@ -162,4 +163,173 @@ describe('Entitlement Pools Module Tests', function () {
});
});
+ it('Load Limits List', () => {
+
+ const limitsList = LimitItemFactory.buildList(3);
+ deepFreeze(limitsList);
+ const store = storeCreator();
+ deepFreeze(store.getState());
+
+ const expectedStore = cloneAndSet(store.getState(), 'licenseModel.entitlementPool.entitlementPoolEditor.limitsList', limitsList);
+ const entitlementPool = EntitlementPoolStoreFactory.build();
+ mockRest.addHandler('fetch', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/entitlement-pools/${entitlementPool.id}/limits`);
+ expect(data).toEqual(undefined);
+ expect(options).toEqual(undefined);
+ return {results: limitsList};
+ });
+
+ return EntitlementPoolsActionHelper.fetchLimits(store.dispatch, {licenseModelId: LICENSE_MODEL_ID, version, entitlementPool}).then(() => {
+ expect(store.getState()).toEqual(expectedStore);
+ });
+ });
+
+ it('Add Limit', () => {
+
+ const store = storeCreator();
+ deepFreeze(store.getState());
+
+ const limitToAdd = LimitPostFactory.build();
+
+ deepFreeze(limitToAdd);
+
+ const LimitIdFromResponse = 'ADDED_ID';
+ const limitAddedItem = {...limitToAdd, id: LimitIdFromResponse};
+ deepFreeze(limitAddedItem);
+ const entitlementPool = EntitlementPoolStoreFactory.build();
+
+ const expectedStore = cloneAndSet(store.getState(), 'licenseModel.entitlementPool.entitlementPoolEditor.limitsList', [limitAddedItem]);
+
+ mockRest.addHandler('post', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/entitlement-pools/${entitlementPool.id}/limits`);
+ expect(data).toEqual(limitToAdd);
+ expect(options).toEqual(undefined);
+ return {
+ returnCode: 'OK',
+ value: LimitIdFromResponse
+ };
+ });
+
+ mockRest.addHandler('fetch', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/entitlement-pools/${entitlementPool.id}/limits`);
+ expect(data).toEqual(undefined);
+ expect(options).toEqual(undefined);
+ return {results: [limitAddedItem]};
+ });
+
+ return EntitlementPoolsActionHelper.submitLimit(store.dispatch,
+ {
+ licenseModelId: LICENSE_MODEL_ID,
+ version,
+ entitlementPool,
+ limit: limitToAdd
+ }
+ ).then(() => {
+ expect(store.getState()).toEqual(expectedStore);
+ });
+ });
+
+
+ it('Delete Limit', () => {
+
+ const limitsList = LimitItemFactory.buildList(1);
+ deepFreeze(limitsList);
+
+ const store = storeCreator({
+ licenseModel: {
+ entitlementPool: {
+ entitlementPoolEditor: {
+ limitsList
+ }
+ }
+ }
+ });
+ deepFreeze(store.getState());
+
+ const entitlementPool = EntitlementPoolStoreFactory.build();
+ const expectedStore = cloneAndSet(store.getState(), 'licenseModel.entitlementPool.entitlementPoolEditor.limitsList', []);
+
+ mockRest.addHandler('destroy', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/entitlement-pools/${entitlementPool.id}/limits/${limitsList[0].id}`);
+ expect(data).toEqual(undefined);
+ expect(options).toEqual(undefined);
+ return {
+ results: {
+ returnCode: 'OK'
+ }
+ };
+ });
+
+ mockRest.addHandler('fetch', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/entitlement-pools/${entitlementPool.id}/limits`);
+ expect(data).toEqual(undefined);
+ expect(options).toEqual(undefined);
+ return {results: []};
+ });
+
+ return EntitlementPoolsActionHelper.deleteLimit(store.dispatch, {
+ licenseModelId: LICENSE_MODEL_ID,
+ version,
+ entitlementPool,
+ limit: limitsList[0]
+ }).then(() => {
+ expect(store.getState()).toEqual(expectedStore);
+ });
+ });
+
+ it('Update Limit', () => {
+
+ const limitsList = LimitItemFactory.buildList(1);
+ deepFreeze(limitsList);
+ const entitlementPool = EntitlementPoolStoreFactory.build();
+ const store = storeCreator({
+ licenseModel: {
+ entitlementPool: {
+ entitlementPoolEditor: {
+ limitsList
+ }
+ }
+ }
+ });
+
+ deepFreeze(store.getState());
+
+
+ const previousData = limitsList[0];
+ deepFreeze(previousData);
+ const limitId = limitsList[0].id;
+
+ const updatedLimit = {...previousData, name: 'updatedLimit'};
+ deepFreeze(updatedLimit);
+ const updatedLimitForPut = {...updatedLimit, id: undefined};
+
+ const expectedStore = cloneAndSet(store.getState(), 'licenseModel.entitlementPool.entitlementPoolEditor.limitsList', [updatedLimit]);
+
+
+ mockRest.addHandler('put', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/entitlement-pools/${entitlementPool.id}/limits/${limitId}`);
+ expect(data).toEqual(updatedLimitForPut);
+ expect(options).toEqual(undefined);
+ return {returnCode: 'OK'};
+ });
+
+ mockRest.addHandler('fetch', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/entitlement-pools/${entitlementPool.id}/limits`);
+ expect(data).toEqual(undefined);
+ expect(options).toEqual(undefined);
+ return {results: [updatedLimit]};
+ });
+
+ return EntitlementPoolsActionHelper.submitLimit(store.dispatch,
+ {
+ licenseModelId: LICENSE_MODEL_ID,
+ version,
+ entitlementPool,
+ limit: updatedLimit
+ }
+ ).then(() => {
+ expect(store.getState()).toEqual(expectedStore);
+ });
+ });
+
});
diff --git a/openecomp-ui/test/licenseModel/licenseKeyGroups/test.js b/openecomp-ui/test/licenseModel/licenseKeyGroups/test.js
index dd09030f4f..77fcc00694 100644
--- a/openecomp-ui/test/licenseModel/licenseKeyGroups/test.js
+++ b/openecomp-ui/test/licenseModel/licenseKeyGroups/test.js
@@ -21,6 +21,7 @@ import {LicenseKeyGroupStoreFactory, LicenseKeyGroupPostFactory} from 'test-util
import LicenseKeyGroupsActionHelper from 'sdc-app/onboarding/licenseModel/licenseKeyGroups/LicenseKeyGroupsActionHelper.js';
import VersionControllerUtilsFactory from 'test-utils/factories/softwareProduct/VersionControllerUtilsFactory.js';
+import {LimitItemFactory, LimitPostFactory} from 'test-utils/factories/licenseModel/LimitFactories.js';
describe('License Key Groups Module Tests', function () {
@@ -157,4 +158,172 @@ describe('License Key Groups Module Tests', function () {
});
});
+ it('Load Limits List', () => {
+
+ const limitsList = LimitItemFactory.buildList(3);
+ deepFreeze(limitsList);
+ const store = storeCreator();
+ deepFreeze(store.getState());
+
+ const expectedStore = cloneAndSet(store.getState(), 'licenseModel.licenseKeyGroup.licenseKeyGroupsEditor.limitsList', limitsList);
+ const licenseKeyGroup = LicenseKeyGroupStoreFactory.build();
+ mockRest.addHandler('fetch', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/license-key-groups/${licenseKeyGroup.id}/limits`);
+ expect(data).toEqual(undefined);
+ expect(options).toEqual(undefined);
+ return {results: limitsList};
+ });
+
+ return LicenseKeyGroupsActionHelper.fetchLimits(store.dispatch, {licenseModelId: LICENSE_MODEL_ID, version, licenseKeyGroup}).then(() => {
+ expect(store.getState()).toEqual(expectedStore);
+ });
+ });
+
+ it('Add Limit', () => {
+
+ const store = storeCreator();
+ deepFreeze(store.getState());
+
+ const limitToAdd = LimitPostFactory.build();
+
+ deepFreeze(limitToAdd);
+
+ const LimitIdFromResponse = 'ADDED_ID';
+ const limitAddedItem = {...limitToAdd, id: LimitIdFromResponse};
+ deepFreeze(limitAddedItem);
+ const licenseKeyGroup = LicenseKeyGroupStoreFactory.build();
+
+ const expectedStore = cloneAndSet(store.getState(), 'licenseModel.licenseKeyGroup.licenseKeyGroupsEditor.limitsList', [limitAddedItem]);
+
+ mockRest.addHandler('post', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/license-key-groups/${licenseKeyGroup.id}/limits`);
+ expect(data).toEqual(limitToAdd);
+ expect(options).toEqual(undefined);
+ return {
+ returnCode: 'OK',
+ value: LimitIdFromResponse
+ };
+ });
+
+ mockRest.addHandler('fetch', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/license-key-groups/${licenseKeyGroup.id}/limits`);
+ expect(data).toEqual(undefined);
+ expect(options).toEqual(undefined);
+ return {results: [limitAddedItem]};
+ });
+
+ return LicenseKeyGroupsActionHelper.submitLimit(store.dispatch,
+ {
+ licenseModelId: LICENSE_MODEL_ID,
+ version,
+ licenseKeyGroup,
+ limit: limitToAdd
+ }
+ ).then(() => {
+ expect(store.getState()).toEqual(expectedStore);
+ });
+ });
+
+ it('Delete Limit', () => {
+
+ const limitsList = LimitItemFactory.buildList(1);
+ deepFreeze(limitsList);
+
+ const store = storeCreator({
+ licenseModel: {
+ entitlementPool: {
+ entitlementPoolEditor: {
+ limitsList
+ }
+ }
+ }
+ });
+ deepFreeze(store.getState());
+
+ const licenseKeyGroup = LicenseKeyGroupStoreFactory.build();
+ const expectedStore = cloneAndSet(store.getState(), 'licenseModel.licenseKeyGroup.licenseKeyGroupsEditor.limitsList', []);
+
+ mockRest.addHandler('destroy', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/license-key-groups/${licenseKeyGroup.id}/limits/${limitsList[0].id}`);
+ expect(data).toEqual(undefined);
+ expect(options).toEqual(undefined);
+ return {
+ results: {
+ returnCode: 'OK'
+ }
+ };
+ });
+
+ mockRest.addHandler('fetch', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/license-key-groups/${licenseKeyGroup.id}/limits`);
+ expect(data).toEqual(undefined);
+ expect(options).toEqual(undefined);
+ return {results: []};
+ });
+
+ return LicenseKeyGroupsActionHelper.deleteLimit(store.dispatch, {
+ licenseModelId: LICENSE_MODEL_ID,
+ version,
+ licenseKeyGroup,
+ limit: limitsList[0]
+ }).then(() => {
+ expect(store.getState()).toEqual(expectedStore);
+ });
+ });
+
+ it('Update Limit', () => {
+
+ const limitsList = LimitItemFactory.buildList(1);
+ deepFreeze(limitsList);
+ const licenseKeyGroup = LicenseKeyGroupStoreFactory.build();
+ const store = storeCreator({
+ licenseModel: {
+ licenseKeyGroup: {
+ licenseKeyGroupsEditor: {
+ limitsList
+ }
+ }
+ }
+ });
+
+ deepFreeze(store.getState());
+
+
+ const previousData = limitsList[0];
+ deepFreeze(previousData);
+ const limitId = limitsList[0].id;
+
+ const updatedLimit = {...previousData, name: 'updatedLimit'};
+ deepFreeze(updatedLimit);
+ const updatedLimitForPut = {...updatedLimit, id: undefined};
+
+ const expectedStore = cloneAndSet(store.getState(), 'licenseModel.licenseKeyGroup.licenseKeyGroupsEditor.limitsList', [updatedLimit]);
+
+
+ mockRest.addHandler('put', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/license-key-groups/${licenseKeyGroup.id}/limits/${limitId}`);
+ expect(data).toEqual(updatedLimitForPut);
+ expect(options).toEqual(undefined);
+ return {returnCode: 'OK'};
+ });
+
+ mockRest.addHandler('fetch', ({data, options, baseUrl}) => {
+ expect(baseUrl).toEqual(`/onboarding-api/v1.0/vendor-license-models/${LICENSE_MODEL_ID}/versions/${version.id}/license-key-groups/${licenseKeyGroup.id}/limits`);
+ expect(data).toEqual(undefined);
+ expect(options).toEqual(undefined);
+ return {results: [updatedLimit]};
+ });
+
+ return LicenseKeyGroupsActionHelper.submitLimit(store.dispatch,
+ {
+ licenseModelId: LICENSE_MODEL_ID,
+ version,
+ licenseKeyGroup,
+ limit: updatedLimit
+ }
+ ).then(() => {
+ expect(store.getState()).toEqual(expectedStore);
+ });
+ });
+
});