Onboarding filter 91/40191/9
authorsvishnev <shlomo-stanisla.vishnevetskiy@amdocs.com>
Sun, 15 Apr 2018 06:06:57 +0000 (09:06 +0300)
committerEinav Keidar <einavw@amdocs.com>
Sun, 15 Apr 2018 07:55:06 +0000 (07:55 +0000)
Issue-ID: SDC-1187
Change-Id: I74ce464c8ee4060c381b094d26d1ded270cdf40d
Signed-off-by: svishnev <shlomo-stanisla.vishnevetskiy@amdocs.com>
50 files changed:
openecomp-ui/package.json
openecomp-ui/resources/scss/_components.scss
openecomp-ui/resources/scss/components/_accordion.scss [deleted file]
openecomp-ui/resources/scss/modules/onboardingCatalog/_catalogFilter.scss
openecomp-ui/resources/scss/modules/onboardingCatalog/_catalogList.scss
openecomp-ui/src/nfvo-components/accordion/Accordion.jsx [deleted file]
openecomp-ui/src/nfvo-utils/i18n/en.json
openecomp-ui/src/nfvo-utils/objectPropsToUrlString.js [new file with mode: 0644]
openecomp-ui/src/sdc-app/AppStore.js
openecomp-ui/src/sdc-app/common/helpers/ItemsHelper.js
openecomp-ui/src/sdc-app/common/helpers/ItemsHelperConstants.js [new file with mode: 0644]
openecomp-ui/src/sdc-app/common/helpers/UniqueTypesHelper.js [new file with mode: 0644]
openecomp-ui/src/sdc-app/features/featureToggle.js
openecomp-ui/src/sdc-app/features/featureToggleUtils.js [moved from openecomp-ui/src/sdc-app/features/restToggle.js with 72% similarity]
openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
openecomp-ui/src/sdc-app/onboarding/OnboardingPunchOut.jsx
openecomp-ui/src/sdc-app/onboarding/OnboardingReducersMap.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationReducer.js
openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationViewWithFilter.jsx [new file with mode: 0644]
openecomp-ui/src/sdc-app/onboarding/onboard/CatalogItemDetails.stories.js
openecomp-ui/src/sdc-app/onboarding/onboard/DetailsCatalogView.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/Onboard.js
openecomp-ui/src/sdc-app/onboarding/onboard/OnboardActionHelper.js
openecomp-ui/src/sdc-app/onboarding/onboard/OnboardView.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/filter/Filter.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterActionHelper.js [new file with mode: 0644]
openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterComponents.jsx [new file with mode: 0644]
openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterConstants.js
openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterMiddleware.js [new file with mode: 0644]
openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterReducer.js
openecomp-ui/src/sdc-app/onboarding/onboard/filter/ItemsReducer.js [new file with mode: 0644]
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogView.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogViewWithFilter.jsx [new file with mode: 0644]
openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/VendorItem.jsx
openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceViewWithFilter.jsx [new file with mode: 0644]
openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProductActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreation.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationActionHelper.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationConstants.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationReducer.js
openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationViewWithFilter.jsx [new file with mode: 0644]
openecomp-ui/test-utils/factories/common/ItemsHelperFactory.js [new file with mode: 0644]
openecomp-ui/test-utils/factories/onboard/FilterFactories.js [new file with mode: 0644]
openecomp-ui/test-utils/factories/onboard/OnboardFactories.js
openecomp-ui/test/onboard/filter/filter.test.js [new file with mode: 0644]
openecomp-ui/test/onboard/filter/filterView.test.js [new file with mode: 0644]
openecomp-ui/test/onboard/test.js
openecomp-ui/yarn.lock

index 70c86cc..6cd9f72 100644 (file)
         "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-failedTestReport":
+            "jest --json | node test-utils/failedTestReport.js",
         "test-dev": "jest --watch",
-        "test-coverage": "jest --coverage && start ./coverage/lcov-report/index.html",
+        "test-coverage":
+            "jest --coverage && start ./coverage/lcov-report/index.html",
         "test-build": "jest --coverage",
-        "storybook": "start-storybook -p 9090 -c .storybook -s .storybook/fonts",
+        "storybook":
+            "start-storybook -p 9090 -c .storybook -s .storybook/fonts",
         "storyshots": "jest storyshots.test.js",
-        "build-storybook": "build-storybook -c .storybook -o .storybook-dist && gulp copy-storybook-fonts",
+        "build-storybook":
+            "build-storybook -c .storybook -o .storybook-dist && gulp copy-storybook-fonts",
         "lint-fix": "eslint --fix  --ext .js --ext .jsx src"
     },
     "dependencies": {
@@ -49,7 +53,7 @@
         "react-show-more": "^1.1.1",
         "react-sortable": "^1.2.0",
         "redux": "^3.7.2",
-        "sdc-ui": "1.6.24",
+        "sdc-ui": "1.6.27",
         "uuid-js": "^0.7.5",
         "validator": "^4.3.0"
     },
     },
     "jest": {
         "moduleNameMapper": {
-            "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/test-utils/fileMock.js",
+            "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$":
+                "<rootDir>/test-utils/fileMock.js",
             "\\.(css|scss)$": "<rootDir>/test-utils/styleMock.js",
             "^nfvo-utils/RestAPIUtil.js$": "<rootDir>/test-utils/MockRest.js",
-            "^sdc-ui/lib/react/SVGIcon.js$": "<rootDir>/test-utils/MockSVGIcon.js",
+            "^sdc-ui/lib/react/SVGIcon.js$":
+                "<rootDir>/test-utils/MockSVGIcon.js",
             "^react-show-more$": "<rootDir>/test-utils/ShowMore.js",
             "^nfvo-utils(.*)$": "<rootDir>/src/nfvo-utils$1",
             "^nfvo-components(.*)$": "<rootDir>/src/nfvo-components$1",
         "globals": {
             "DEBUG": false
         },
-        "setupFiles": [
-            "<rootDir>/test-utils/test-env-setup.js"
-        ],
+        "setupFiles": ["<rootDir>/test-utils/test-env-setup.js"],
         "setupTestFrameworkScriptFile": "<rootDir>/test-utils/test-setup.js",
         "testPathIgnorePatterns": [
             "<rootDir>/node_modules/",
             "<rootDir>/test/nfvo-components/storyshots.test.js"
         ],
-        "collectCoverageFrom": [
-            "src/**/*.{js,jsx}"
-        ],
-        "coveragePathIgnorePatterns": [
-            "/node_modules/",
-            "(.)*.stories.js"
-        ],
-        "coverageReporters": [
-            "lcov"
-        ]
+        "collectCoverageFrom": ["src/**/*.{js,jsx}"],
+        "coveragePathIgnorePatterns": ["/node_modules/", "(.)*.stories.js"],
+        "coverageReporters": ["lcov"]
     }
 }
index ce5c732..e18b260 100644 (file)
@@ -21,7 +21,6 @@
 @import "components/commitModal";
 @import "components/userNotifications";
 @import "components/overlay";
-@import "components/accordion";
 @import "components/vspDetailsVendorSelect";
 
 %noselect {
diff --git a/openecomp-ui/resources/scss/components/_accordion.scss b/openecomp-ui/resources/scss/components/_accordion.scss
deleted file mode 100644 (file)
index c96bc71..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-.accordion {
-    display: flex;
-    flex-direction: column;
-    .accordion-header {
-        display: flex;
-        flex-direction: row;
-        cursor: pointer;
-        margin-bottom: 10px;
-        .svg-icon-wrapper {
-            margin-right: 20px;
-            transition: transform .4s;
-            &.down {
-                transform: rotate(180deg);
-            }
-        }
-    }
-    .accordion-body {
-        padding-left: 10px;                
-        opacity: 0;
-        overflow-y: hidden;
-        max-height: 0;
-        transition: max-height .3s cubic-bezier(0, 1.18, 1, 1), opacity 0.33s linear;
-        &.open {                       
-            opacity: 1;
-            max-height: 100%;
-        }
-    }
-}
\ No newline at end of file
index cda47c6..a7a7628 100644 (file)
@@ -1,16 +1,22 @@
 .catalog-filter {
-    width: 242px;
-    overflow-y: auto;    
-    height: 100%;
-    box-shadow: 1px 0px 4px 0px rgba(24, 24, 25, 0.17);
-    background-color: $white;
-    padding: 12px 18px;    
-    .form-group {
-        margin-bottom: 10px;
+    .catalog-filter-by-vendor-view {
+        margin-left: 18px;
+        margin-right: 18px;
+    }
+    .empty-block {
+        height: 34px;
+        width: 100%;
     }
     .catalog-filter-items-type {
         width: 100%;
-        background-color: $gray;
-        color: $white;
+        background-color: $tlv-light-gray;
+        height: 34px;
+    }
+    .sdc-accordion {
+        padding-left: 18px;
+        padding-right: 18px;
+    }
+    .first-line {
+        margin-top: 40px;
     }
-}
\ No newline at end of file
+}
index 071268c..11a739d 100644 (file)
          display: block;
          width: 100%;
        }
+       .venodor-tile-btn {
+               border: 1px solid $light-gray;
+               color: $black;
+               line-height: 20px;
+               &:hover {
+                               background-color: $light-gray;
+               }
+       }
   }
 
   // Bottom spacing - cross browser solution
diff --git a/openecomp-ui/src/nfvo-components/accordion/Accordion.jsx b/openecomp-ui/src/nfvo-components/accordion/Accordion.jsx
deleted file mode 100644 (file)
index 72f8de0..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright © 2016-2018 European Support Limited
- *
- * 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 SVGIcon from 'sdc-ui/lib/react/SVGIcon.js';
-import PropTypes from 'prop-types';
-
-class Accordion extends React.Component {
-    static propTypes = {
-        title: PropTypes.string,
-        children: PropTypes.node
-    };
-
-    constructor(props) {
-        super(props);
-        this.state = {
-            open: false
-        };
-    }
-    render() {
-        const { children, title } = this.props;
-        const { open } = this.state;
-        return (
-            <div className="accordion">
-                <div
-                    onClick={() => this.setState({ open: !open })}
-                    className="accordion-header">
-                    <SVGIcon
-                        name="chevronUp"
-                        iconClassName={open ? 'down' : ''}
-                    />
-                    <div className="title">{title}</div>
-                </div>
-                <div className={`accordion-body ${open ? 'open' : ''}`}>
-                    {children}
-                </div>
-            </div>
-        );
-    }
-}
-
-export default Accordion;
index 347a8ed..cbc2031 100644 (file)
@@ -83,7 +83,8 @@
   "This software product successfully submitted": "This software product successfully submitted",
   "Submit Failed": "Submit Failed",
   "Vendor Name": "Vendor Name",
-  "License model by the name \\": "License model by the name \\",
+  "License model by the name": "License model by the name",
+  "License model name must be unique": "License model name must be unique",
   "please select…": "please select…",
   "Warning": "Warning",
   "Operational Scope": "Operational Scope",
   "Vendor": "Vendor",
   "Category": "Category",
   "please select...": "please select...",
-  "Software product by the name \\": "Software product by the name \\",
+  "Software product by the name": "Software product by the name",
+  "Software product name must be unique": "Software product name must be unique",
+  "already exists": "already exists",
   "Onboarding procedure": "Onboarding procedure",
   "HEAT file": "HEAT file",
   "Manual": "Manual",
   "Granted": "Granted",
   "Taken": "Taken",
   "Permission": "Permission",
-  
+  "By Vendor View": "By Vendor View",
+  "PERMISSIONS": "PERMISSIONS",
+  "Contributor": "Contributor",
+  "Active Items": "Active Items",
+  "Archived Items": "Archived Items",
+
   "VendorSoftwareProduct": "VSP",
   "VendorSoftwareProduct/category": "Category",
   "VendorSoftwareProduct/description": "Description",
diff --git a/openecomp-ui/src/nfvo-utils/objectPropsToUrlString.js b/openecomp-ui/src/nfvo-utils/objectPropsToUrlString.js
new file mode 100644 (file)
index 0000000..6c18bb6
--- /dev/null
@@ -0,0 +1,23 @@
+export default function objectPropsToUrlString(data) {
+    let str = '';
+    Object.keys(data).map(key => {
+        if (typeof data[key] === 'object') {
+            let obj = data[key];
+            let arr = [];
+
+            Object.keys(obj).map(prop => {
+                if (obj[prop]) {
+                    arr.push(encodeURIComponent(prop));
+                }
+            });
+            if (arr.length) {
+                str += `&${encodeURIComponent(key)}=${arr.join(',')}`;
+            }
+        } else if (data[key]) {
+            str += `&${encodeURIComponent(key)}=${encodeURIComponent(
+                data[key]
+            )}`;
+        }
+    });
+    return str;
+}
index bca750a..5cab6ae 100644 (file)
 
 import { createStore, applyMiddleware, compose } from 'redux';
 import Reducers from './Reducers.js';
+import filterUpdater from 'sdc-app/onboarding/onboard/filter/FilterMiddleware.js';
+
 const thunk = store => next => action =>
     typeof action === 'function'
         ? action(store.dispatch, store.getState)
         : next(action);
 
 const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
+
 export const storeCreator = initialState =>
     createStore(
         Reducers,
         initialState,
-        composeEnhancers(applyMiddleware(thunk))
+        composeEnhancers(applyMiddleware(thunk, filterUpdater))
     );
 
 const store = storeCreator();
index 99ecae9..ae5c270 100644 (file)
@@ -1,36 +1,32 @@
-/*!
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+/*
+ * Copyright © 2016-2018 European Support Limited
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing
- * permissions and limitations under the License.
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
  */
 import RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
 import Configuration from 'sdc-app/config/Configuration.js';
 import { permissionTypes } from 'sdc-app/onboarding/permissions/PermissionsConstants.js';
 import { actionsEnum as VersionControllerActionsEnum } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
 import { actionTypes as onboardingActionTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
-import restToggle from 'sdc-app/features/restToggle.js';
+import { restToggle } from 'sdc-app/features/featureToggleUtils.js';
 import { featureToggleNames } from 'sdc-app/features/FeaturesConstants.js';
+import objectPropsToUrlString from 'nfvo-utils/objectPropsToUrlString.js';
+
 export const archiveActions = {
     ARCHIVE: 'ARCHIVE',
     RESTORE: 'RESTORE'
 };
 
-export const itemStatus = {
-    ARCHIVED: 'ARCHIVED',
-    DRAFT: 'Draft',
-    CERTIFIED: 'Certified'
-};
-
 function baseUrl() {
     const restPrefix = Configuration.get('restPrefix');
     return `${restPrefix}/v1.0/items`;
@@ -118,6 +114,15 @@ const ItemsHelper = {
         return RestAPIUtil.put(`${baseUrl()}/${itemId}/actions`, {
             action: archiveActions.RESTORE
         });
+    },
+
+    fetchItems(filterData) {
+        const str = objectPropsToUrlString(filterData);
+        return restToggle({
+            restFunction: () => RestAPIUtil.fetch(`${baseUrl()}?${str}`),
+            featureName: featureToggleNames.FILTER,
+            mockResult: { results: [] }
+        });
     }
 };
 
diff --git a/openecomp-ui/src/sdc-app/common/helpers/ItemsHelperConstants.js b/openecomp-ui/src/sdc-app/common/helpers/ItemsHelperConstants.js
new file mode 100644 (file)
index 0000000..ebbbfde
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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.
+ */
+export const itemStatus = {
+    ACTIVE: 'ACTIVE',
+    ARCHIVED: 'ARCHIVED'
+};
+
+export const versionStatus = {
+    DRAFT: 'Draft',
+    CERTIFIED: 'Certified'
+};
+
+export const itemType = {
+    VSP: 'vsp',
+    VLM: 'vlm'
+};
diff --git a/openecomp-ui/src/sdc-app/common/helpers/UniqueTypesHelper.js b/openecomp-ui/src/sdc-app/common/helpers/UniqueTypesHelper.js
new file mode 100644 (file)
index 0000000..de84f91
--- /dev/null
@@ -0,0 +1,69 @@
+/*!
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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 RestAPIUtil from 'nfvo-utils/RestAPIUtil.js';
+import Configuration from 'sdc-app/config/Configuration.js';
+import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
+import { featureToggleNames } from 'sdc-app/features/FeaturesConstants.js';
+import { restToggle } from 'sdc-app/features/featureToggleUtils.js';
+
+const itemTypesMapper = {
+    vsp: 'VspName',
+    vlm: 'VlmName'
+};
+
+function baseUrl() {
+    const restPrefix = Configuration.get('restPrefix');
+    return `${restPrefix}/v1.0/unique-types/`;
+}
+
+function uniqueValue(type, value) {
+    return restToggle({
+        restFunction: () =>
+            RestAPIUtil.fetch(`${baseUrl()}${type}/values/${value}`),
+        featureName: featureToggleNames.FILTER,
+        mockResult: { occupied: false }
+    });
+}
+
+export default {
+    async isNameUnique(
+        dispatch,
+        { value, name, formName, errorText, itemType }
+    ) {
+        const { occupied } = await uniqueValue(
+            itemTypesMapper[itemType],
+            value
+        );
+        const validation = occupied
+            ? {
+                  isValid: false,
+                  errorText
+              }
+            : { isValid: true, errorText: '' };
+
+        let deltaData = {};
+        deltaData[name] = value;
+        let customValidations = {};
+        customValidations[name] = () => validation;
+
+        ValidationHelper.dataChanged(dispatch, {
+            deltaData,
+            formName,
+            customValidations
+        });
+    }
+};
index d33c76e..861db6a 100644 (file)
@@ -38,12 +38,14 @@ import { connect } from 'react-redux';
 
 export const FeatureComponent = props => {
     const { features = [], featureName, InnerComponent, ...otherProps } = props;
-    const AComp = InnerComponent.AComp ? InnerComponent.AComp : InnerComponent;
+    const OnComp = InnerComponent.OnComp
+        ? InnerComponent.OnComp
+        : InnerComponent;
 
     return !!features.find(el => el.name === featureName && el.active) ? (
-        <AComp {...otherProps} />
-    ) : InnerComponent.BComp ? (
-        <InnerComponent.BComp {...otherProps} />
+        <OnComp {...otherProps} />
+    ) : InnerComponent.OffComp ? (
+        <InnerComponent.OffComp {...otherProps} />
     ) : null;
 };
 
 
 import store from 'sdc-app/AppStore.js';
 
-export default ({ featureName, restFunction, mockResult }) => {
+export const restToggle = ({ featureName, restFunction, mockResult }) => {
     const { features } = store.getState();
     return !!features.find(el => el.name === featureName && el.active)
         ? restFunction()
         : Promise.resolve(mockResult);
 };
+
+export const functionToggle = (featureName, { onFunction, offFunction }) => {
+    const { features } = store.getState();
+    return !!features.find(el => el.name === featureName && el.active)
+        ? onFunction()
+        : offFunction();
+};
index 2fccfcb..b8ce714 100644 (file)
@@ -45,6 +45,8 @@ import SoftwareProductComponentsImageActionHelper from './softwareProduct/compon
 import licenseModelOverviewActionHelper from 'sdc-app/onboarding/licenseModel/overview/licenseModelOverviewActionHelper.js';
 import { tabsMapping as attachmentsTabsMapping } from 'sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsConstants.js';
 import SoftwareProductAttachmentsActionHelper from 'sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachmentsActionHelper.js';
+import { actionTypes as filterActionTypes } from './onboard/filter/FilterConstants.js';
+import FeaturesActionHelper from 'sdc-app/features/FeaturesActionHelper.js';
 
 function setCurrentScreen(dispatch, screen, props = {}) {
     dispatch({
@@ -74,11 +76,16 @@ const OnboardingActionHelper = {
         SoftwareProductActionHelper.fetchArchivedSoftwareProductList(dispatch);
     },
 
-    navigateToOnboardingCatalog(dispatch) {
+    async navigateToOnboardingCatalog(dispatch) {
+        await FeaturesActionHelper.getFeaturesList(dispatch);
         UsersActionHelper.fetchUsersList(dispatch);
         this.loadItemsLists(dispatch);
         OnboardActionHelper.resetOnboardStore(dispatch);
         setCurrentScreen(dispatch, enums.SCREEN.ONBOARDING_CATALOG);
+        dispatch({
+            type: filterActionTypes.FILTER_DATA_CHANGED,
+            deltaData: {}
+        });
     },
 
     autoSaveBeforeNavigate(
@@ -207,6 +214,7 @@ const OnboardingActionHelper = {
         { softwareProductId, version, status }
     ) {
         SoftwareProductComponentsActionHelper.clearComponentsStore(dispatch);
+        LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch);
         SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {
             softwareProductId,
             version
@@ -559,7 +567,7 @@ const OnboardingActionHelper = {
         );
     },
 
-    navigateToVersionsPage(
+    async navigateToVersionsPage(
         dispatch,
         { itemType, itemId, itemName, additionalProps, users }
     ) {
@@ -568,19 +576,19 @@ const OnboardingActionHelper = {
             allUsers: users
         });
         VersionsPageActionHelper.selectNone(dispatch);
-        VersionsPageActionHelper.fetchVersions(dispatch, {
+        await VersionsPageActionHelper.fetchVersions(dispatch, {
             itemType,
             itemId
-        }).then(() => {
-            ItemsHelper.fetchItem(itemId).then(result => {
-                setCurrentScreen(dispatch, enums.SCREEN.VERSIONS_PAGE, {
-                    status: result.status,
-                    itemType,
-                    itemId,
-                    itemName,
-                    additionalProps
-                });
-            });
+        });
+        const items = await ItemsHelper.fetchItem(itemId);
+        setCurrentScreen(dispatch, enums.SCREEN.VERSIONS_PAGE, {
+            status: items.status,
+            itemType,
+            itemId,
+            itemName,
+            vendorName: items.properties.vendorName,
+            vendorId: items.properties.vendorId,
+            additionalProps
         });
     },
 
index f462dd7..245dd2b 100644 (file)
@@ -21,8 +21,6 @@ import ReactDOM from 'react-dom';
 
 import isEqual from 'lodash/isEqual.js';
 
-import lodashUnionBy from 'lodash/unionBy.js';
-
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import Application from 'sdc-app/Application.jsx';
 import store from 'sdc-app/AppStore.js';
@@ -356,10 +354,6 @@ export default class OnboardingPunchOut {
     handleStoreChange() {
         let {
             currentScreen,
-            licenseModelList,
-            finalizedLicenseModelList,
-            softwareProductList,
-            finalizedSoftwareProductList,
             versionsPage: { versionsList: { itemType, itemId } },
             softwareProduct: {
                 softwareProductEditor: {
@@ -367,26 +361,17 @@ export default class OnboardingPunchOut {
                 },
                 softwareProductComponents: { componentsList }
             },
-            archivedLicenseModelList,
-            archivedSoftwareProductList
+            licenseModel: {
+                licenseModelEditor: { data: currentLicenseModel = {} }
+            }
         } = store.getState();
-        const wholeSoftwareProductList = lodashUnionBy(
-            softwareProductList,
-            [...finalizedSoftwareProductList, ...archivedSoftwareProductList],
-            'id'
-        );
-        const wholeLicenseModelList = lodashUnionBy(
-            licenseModelList,
-            [...finalizedLicenseModelList, ...archivedLicenseModelList],
-            'id'
-        );
+
         let breadcrumbsData = {
             itemType,
             itemId,
             currentScreen,
-            wholeLicenseModelList,
-            wholeSoftwareProductList,
             currentSoftwareProduct,
+            currentLicenseModel,
             componentsList
         };
 
@@ -415,8 +400,7 @@ export default class OnboardingPunchOut {
         itemType,
         itemId,
         currentSoftwareProduct,
-        wholeLicenseModelList,
-        wholeSoftwareProductList,
+        currentLicenseModel,
         componentsList
     }) {
         let {
@@ -435,12 +419,12 @@ export default class OnboardingPunchOut {
                         ? [
                               {
                                   selectedKey: itemId,
-                                  menuItems: wholeLicenseModelList.map(
-                                      ({ id, name }) => ({
-                                          key: id,
-                                          displayText: name
-                                      })
-                                  )
+                                  menuItems: [
+                                      {
+                                          key: itemId,
+                                          displayText: props.itemName
+                                      }
+                                  ]
                               }
                           ]
                         : [
@@ -448,12 +432,12 @@ export default class OnboardingPunchOut {
                                   selectedKey:
                                       props.additionalProps.licenseModelId ||
                                       currentSoftwareProduct.vendorId,
-                                  menuItems: wholeLicenseModelList.map(
-                                      ({ id, name }) => ({
-                                          key: id,
-                                          displayText: name
-                                      })
-                                  )
+                                  menuItems: [
+                                      {
+                                          key: props.vendorId,
+                                          displayText: props.vendorName
+                                      }
+                                  ]
                               },
                               {
                                   selectedKey:
@@ -472,17 +456,12 @@ export default class OnboardingPunchOut {
                               },
                               {
                                   selectedKey: itemId,
-                                  menuItems: wholeSoftwareProductList
-                                      .filter(
-                                          ({ id, vendorId }) =>
-                                              vendorId ===
-                                                  currentSoftwareProduct.vendorId ||
-                                              id === itemId
-                                      )
-                                      .map(({ id, name }) => ({
-                                          key: id,
-                                          displayText: name
-                                      }))
+                                  menuItems: [
+                                      {
+                                          key: itemId,
+                                          displayText: props.itemName
+                                      }
+                                  ]
                               }
                           ];
                 return [
@@ -519,13 +498,13 @@ export default class OnboardingPunchOut {
                 };
                 return [
                     {
-                        selectedKey: props.licenseModelId,
-                        menuItems: wholeLicenseModelList.map(
-                            ({ id, name }) => ({
-                                key: id,
-                                displayText: name
-                            })
-                        )
+                        selectedKey: currentLicenseModel.id,
+                        menuItems: [
+                            {
+                                key: currentLicenseModel.id,
+                                displayText: currentLicenseModel.vendorName
+                            }
+                        ]
                     },
                     {
                         selectedKey: enums.BREADCRUMS.LICENSE_MODEL,
@@ -533,19 +512,7 @@ export default class OnboardingPunchOut {
                             {
                                 key: enums.BREADCRUMS.LICENSE_MODEL,
                                 displayText: i18n('License Model')
-                            },
-                            ...(wholeSoftwareProductList.findIndex(
-                                ({ vendorId }) =>
-                                    vendorId === props.licenseModelId
-                            ) === -1
-                                ? []
-                                : [
-                                      {
-                                          key:
-                                              enums.BREADCRUMS.SOFTWARE_PRODUCT,
-                                          displayText: i18n('Software Products')
-                                      }
-                                  ])
+                            }
                         ]
                     },
                     {
@@ -636,16 +603,16 @@ export default class OnboardingPunchOut {
                     [enums.SCREEN.SOFTWARE_PRODUCT_COMPONENT_MONITORING]:
                         enums.BREADCRUMS.SOFTWARE_PRODUCT_COMPONENT_MONITORING
                 };
-                let licenseModelId = currentSoftwareProduct.vendorId;
+
                 let returnedBreadcrumb = [
                     {
-                        selectedKey: licenseModelId,
-                        menuItems: wholeLicenseModelList.map(
-                            ({ id, name }) => ({
-                                key: id,
-                                displayText: name
-                            })
-                        )
+                        selectedKey: currentSoftwareProduct.vendorId,
+                        menuItems: [
+                            {
+                                key: currentSoftwareProduct.vendorId,
+                                displayText: currentSoftwareProduct.vendorName
+                            }
+                        ]
                     },
                     {
                         selectedKey: enums.BREADCRUMS.SOFTWARE_PRODUCT,
@@ -661,17 +628,13 @@ export default class OnboardingPunchOut {
                         ]
                     },
                     {
-                        selectedKey: props.softwareProductId,
-                        menuItems: wholeSoftwareProductList
-                            .filter(
-                                ({ vendorId, id }) =>
-                                    vendorId === licenseModelId ||
-                                    id === props.softwareProductId
-                            )
-                            .map(({ id, name }) => ({
-                                key: id,
-                                displayText: name
-                            }))
+                        selectedKey: currentSoftwareProduct.id,
+                        menuItems: [
+                            {
+                                key: currentSoftwareProduct.id,
+                                displayText: currentSoftwareProduct.name
+                            }
+                        ]
                     },
                     .../*screen === enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE ? [] :*/ [
                         {
index 3b526a6..09f4ffb 100644 (file)
@@ -28,7 +28,7 @@ import usersReducer from './users/UsersReducers.js';
 import mergeEditorReducer from 'sdc-app/common/merge/MergeEditorReducer.js';
 import revisionsReducer from './revisions/RevisionsReducer.js';
 import featuresReducer from 'sdc-app/features/FeaturesReducer.js';
-
+import itemsReducer from 'sdc-app/onboarding/onboard/filter/ItemsReducer.js';
 export default {
     currentScreen: currentScreenReducer,
     licenseModel: licenseModelReducer,
@@ -44,5 +44,6 @@ export default {
     users: usersReducer,
     versionsPage: versionsPageReducer,
     revisions: revisionsReducer,
-    features: featuresReducer
+    features: featuresReducer,
+    filteredItems: itemsReducer
 };
index cfff9f1..be33af7 100644 (file)
@@ -29,8 +29,11 @@ import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
 import { CommitModalType } from 'nfvo-components/panel/versionController/components/CommitCommentModal.jsx';
 import versionPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
 import { itemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
-import { catalogItemStatuses } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
 import { actionsEnum as VersionControllerActionsEnum } from 'nfvo-components/panel/versionController/VersionControllerConstants.js';
+import {
+    itemStatus,
+    versionStatus
+} from 'sdc-app/common/helpers/ItemsHelperConstants.js';
 
 function baseUrl() {
     const restPrefix = Configuration.get('restPrefix');
@@ -39,19 +42,17 @@ function baseUrl() {
 
 function fetchLicenseModels() {
     return RestAPIUtil.fetch(
-        `${baseUrl()}?versionFilter=${catalogItemStatuses.DRAFT}`
+        `${baseUrl()}?versionFilter=${versionStatus.DRAFT}`
     );
 }
 
 function fetchFinalizedLicenseModels() {
     return RestAPIUtil.fetch(
-        `${baseUrl()}?versionFilter=${catalogItemStatuses.CERTIFIED}`
+        `${baseUrl()}?versionFilter=${versionStatus.CERTIFIED}`
     );
 }
 function fetchArchivedLicenseModels() {
-    return RestAPIUtil.fetch(
-        `${baseUrl()}?Status=${catalogItemStatuses.ARCHIVED}`
-    );
+    return RestAPIUtil.fetch(`${baseUrl()}?Status=${itemStatus.ARCHIVED}`);
 }
 function fetchLicenseModelById(licenseModelId, version) {
     const { id: versionId } = version;
@@ -206,9 +207,8 @@ const LicenseModelActionHelper = {
             version
         }).then(({ inMerge, isDirty, updatedVersion }) => {
             if (
-                (updatedVersion.status === catalogItemStatuses.CERTIFIED ||
-                    updatedVersion.archivedStatus ===
-                        catalogItemStatuses.ARCHIVED) &&
+                (updatedVersion.status === versionStatus.CERTIFIED ||
+                    updatedVersion.archivedStatus === versionStatus.ARCHIVED) &&
                 (action === VersionControllerActionsEnum.COMMIT ||
                     action === VersionControllerActionsEnum.SYNC)
             ) {
@@ -217,8 +217,7 @@ const LicenseModelActionHelper = {
                     itemId: licenseModelId
                 });
                 const msg =
-                    updatedVersion.archivedStatus ===
-                    catalogItemStatuses.ARCHIVED
+                    updatedVersion.archivedStatus === versionStatus.ARCHIVED
                         ? i18n('Item was Archived')
                         : i18n('Item version already Certified');
                 dispatch({
index 4bbab86..c6a0702 100644 (file)
  * limitations under the License.
  */
 import { connect } from 'react-redux';
+import featureToggle from 'sdc-app/features/featureToggle.js';
+import { featureToggleNames } from 'sdc-app/features/FeaturesConstants.js';
 import LicenseModelCreationActionHelper from './LicenseModelCreationActionHelper.js';
 import LicenseModelCreationView from './LicenseModelCreationView.jsx';
+import LicenseModelCreationViewWithFilter from './LicenseModelCreationViewWithFilter.jsx';
+
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import LicenseModelActionHelper from 'sdc-app/onboarding/licenseModel/LicenseModelActionHelper.js';
 import VersionsPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
@@ -23,6 +27,16 @@ import { itemTypes as versionItemTypes } from 'sdc-app/onboarding/versionsPage/V
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
 import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import PermissionsActionHelper from 'sdc-app/onboarding/permissions/PermissionsActionHelper.js';
+import UniqueTypesHelper from 'sdc-app/common/helpers/UniqueTypesHelper.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import { itemType } from 'sdc-app/common/helpers/ItemsHelperConstants.js';
+
+const ToggledLicenseModelCreationView = featureToggle(
+    featureToggleNames.FILTER
+)({
+    OnComp: LicenseModelCreationViewWithFilter,
+    OffComp: LicenseModelCreationView
+});
 
 export const mapStateToProps = ({
     users: { usersList },
@@ -87,10 +101,22 @@ export const mapActionsToProps = dispatch => {
             });
         },
         onValidateForm: formName =>
-            ValidationHelper.validateForm(dispatch, formName)
+            ValidationHelper.validateForm(dispatch, formName),
+        isNameUnique: (value, name, formName) =>
+            UniqueTypesHelper.isNameUnique(dispatch, {
+                value,
+                name,
+                formName,
+                errorText: `${i18n(
+                    'License model by the name'
+                )} ${value} ${i18n('already exists')}. ${i18n(
+                    'License model name must be unique'
+                )}`,
+                itemType: itemType.VLM
+            })
     };
 };
 
 export default connect(mapStateToProps, mapActionsToProps)(
-    LicenseModelCreationView
+    ToggledLicenseModelCreationView
 );
index 7137230..5922a47 100644 (file)
@@ -40,7 +40,8 @@ export default (state = {}, action) => {
                         errorText: '',
                         validations: [
                             { type: 'required', data: true },
-                            { type: 'maxLength', data: 25 }
+                            { type: 'maxLength', data: 25 },
+                            { type: 'validateName', data: true }
                         ]
                     }
                 }
diff --git a/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationViewWithFilter.jsx b/openecomp-ui/src/sdc-app/onboarding/licenseModel/creation/LicenseModelCreationViewWithFilter.jsx
new file mode 100644 (file)
index 0000000..8c5d966
--- /dev/null
@@ -0,0 +1,116 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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 PropTypes from 'prop-types';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import { LICENSE_MODEL_CREATION_FORM_NAME } from './LicenseModelCreationConstants.js';
+
+const LicenseModelPropType = PropTypes.shape({
+    id: PropTypes.string,
+    vendorName: PropTypes.string,
+    description: PropTypes.string
+});
+
+class LicenseModelCreationView extends React.Component {
+    static propTypes = {
+        data: LicenseModelPropType,
+        VLMNames: PropTypes.object,
+        usersList: PropTypes.array,
+        onDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onValidateForm: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired
+    };
+
+    render() {
+        let { data = {}, onDataChanged, genericFieldInfo } = this.props;
+        let { vendorName, description } = data;
+        return (
+            <div>
+                {genericFieldInfo && (
+                    <Form
+                        ref="validationForm"
+                        hasButtons={true}
+                        onSubmit={() => this.submit()}
+                        submitButtonText={i18n('Create')}
+                        onReset={() => this.props.onCancel()}
+                        labledButtons={true}
+                        isValid={this.props.isFormValid}
+                        formReady={this.props.formReady}
+                        onValidateForm={() => this.validate()}>
+                        <Input
+                            value={vendorName}
+                            label={i18n('Vendor Name')}
+                            data-test-id="vendor-name"
+                            onChange={vendorName =>
+                                onDataChanged(
+                                    { vendorName },
+                                    LICENSE_MODEL_CREATION_FORM_NAME
+                                )
+                            }
+                            onBlur={e =>
+                                this.validateIsNameUnique(e.target.value)
+                            }
+                            isValid={genericFieldInfo.vendorName.isValid}
+                            errorText={genericFieldInfo.vendorName.errorText}
+                            type="text"
+                            isRequired={true}
+                            className="field-section"
+                        />
+                        <Input
+                            isRequired={true}
+                            value={description}
+                            label={i18n('Description')}
+                            data-test-id="vendor-description"
+                            overlayPos="bottom"
+                            onChange={description =>
+                                onDataChanged(
+                                    { description },
+                                    LICENSE_MODEL_CREATION_FORM_NAME
+                                )
+                            }
+                            isValid={genericFieldInfo.description.isValid}
+                            errorText={genericFieldInfo.description.errorText}
+                            type="textarea"
+                            className="field-section"
+                        />
+                    </Form>
+                )}
+            </div>
+        );
+    }
+
+    submit() {
+        const { data: licenseModel, usersList } = this.props;
+        this.props.onSubmit(licenseModel, usersList);
+    }
+
+    validateIsNameUnique(value) {
+        this.props.isNameUnique(
+            value,
+            'vendorName',
+            LICENSE_MODEL_CREATION_FORM_NAME
+        );
+    }
+
+    validate() {
+        this.props.onValidateForm(LICENSE_MODEL_CREATION_FORM_NAME);
+    }
+}
+
+export default LicenseModelCreationView;
index d01b9d0..c0de0ee 100644 (file)
@@ -2,11 +2,9 @@ import React from 'react';
 import { storiesOf, action } from '@kadira/storybook';
 import { select, withKnobs } from '@kadira/storybook-addon-knobs';
 import CatalogItemDetails from './CatalogItemDetails.jsx';
-import {
-    catalogItemTypes,
-    catalogItemStatuses
-} from './onboardingCatalog/OnboardingCatalogConstants.js';
+import { catalogItemTypes } from './onboardingCatalog/OnboardingCatalogConstants.js';
 import { FinalizedLicenseModelFactory } from 'test-utils/factories/licenseModel/LicenseModelFactories.js';
+import { versionStatus } from 'sdc-app/common/helpers/ItemsHelperConstants.js';
 
 const stories = storiesOf('CatalogTiles', module);
 stories.addDecorator(withKnobs);
@@ -22,9 +20,9 @@ function selectType() {
 
 let vlm = {
     ...FinalizedLicenseModelFactory.build({ name: 'Test-VLM' }),
-    itemStatus: catalogItemStatuses.DRAFT
+    itemStatus: versionStatus.DRAFT
 };
-let certifiedVlm = { ...vlm, itemStatus: catalogItemStatuses.CERTIFIED };
+let certifiedVlm = { ...vlm, itemStatus: versionStatus.CERTIFIED };
 
 stories.add('preview', () => (
     <div className="catalog-view">
index 771c0eb..b535595 100644 (file)
@@ -13,6 +13,7 @@
  * or implied. See the License for the specific language governing
  * permissions and limitations under the License.
  */
+import isEqual from 'lodash/isEqual.js';
 import React from 'react';
 import PropTypes from 'prop-types';
 import { catalogItemTypes } from './onboardingCatalog/OnboardingCatalogConstants.js';
@@ -20,6 +21,28 @@ import { filterCatalogItemsByType } from './onboardingCatalog/OnboardingCatalogU
 import CatalogList from './CatalogList.jsx';
 import CatalogItemDetails from './CatalogItemDetails.jsx';
 
+function renderCatalogItems({
+    items,
+    type,
+    filter,
+    onSelect,
+    onMigrate,
+    users
+}) {
+    const filteredItems = items.length
+        ? filterCatalogItemsByType({ items, filter })
+        : [];
+    return filteredItems.map(item => (
+        <CatalogItemDetails
+            key={item.id}
+            catalogItemData={item}
+            catalogItemTypeClass={type}
+            onMigrate={onMigrate}
+            onSelect={() => onSelect(item, users)}
+        />
+    ));
+}
+
 class DetailsCatalogView extends React.Component {
     static propTypes = {
         VLMList: PropTypes.array,
@@ -31,18 +54,14 @@ class DetailsCatalogView extends React.Component {
         filter: PropTypes.string.isRequired
     };
 
-    renderCatalogItems({ items, type, filter, onSelect, onMigrate, users }) {
-        return filterCatalogItemsByType({ items, filter }).map(item => (
-            <CatalogItemDetails
-                key={item.id}
-                catalogItemData={item}
-                catalogItemTypeClass={type}
-                onMigrate={onMigrate}
-                onSelect={() => onSelect(item, users)}
-            />
-        ));
+    shouldComponentUpdate(nextProps) {
+        const shouldUpdate =
+            isEqual(nextProps.VLMList, this.props.VLMList) &&
+            isEqual(nextProps.VSPList, this.props.VSPList) &&
+            isEqual(nextProps.users, this.props.users) &&
+            isEqual(nextProps.filter, this.props.filter);
+        return !shouldUpdate;
     }
-
     render() {
         let {
             VLMList,
@@ -57,7 +76,7 @@ class DetailsCatalogView extends React.Component {
         } = this.props;
         return (
             <CatalogList onAddVLM={onAddVLM} onAddVSP={onAddVSP}>
-                {this.renderCatalogItems({
+                {renderCatalogItems({
                     items: VLMList,
                     type: catalogItemTypes.LICENSE_MODEL,
                     filter,
@@ -65,7 +84,7 @@ class DetailsCatalogView extends React.Component {
                     onMigrate,
                     users
                 })}
-                {this.renderCatalogItems({
+                {renderCatalogItems({
                     items: VSPList,
                     type: catalogItemTypes.SOFTWARE_PRODUCT,
                     filter,
index a1e0018..ea70f9c 100644 (file)
@@ -22,7 +22,7 @@ import LicenseModelCreationActionHelper from '../licenseModel/creation/LicenseMo
 import SoftwareProductCreationActionHelper from '../softwareProduct/creation/SoftwareProductCreationActionHelper.js';
 import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
 import { tabsMapping } from './onboardingCatalog/OnboardingCatalogConstants.js';
-import { itemsType } from './filter/FilterConstants.js';
+import { itemStatus } from 'sdc-app/common/helpers/ItemsHelperConstants.js';
 
 export const mapStateToProps = ({
     onboard: { onboardingCatalog, activeTab, searchValue, filter },
@@ -32,7 +32,8 @@ export const mapStateToProps = ({
     archivedSoftwareProductList,
     finalizedLicenseModelList,
     softwareProductList,
-    finalizedSoftwareProductList
+    finalizedSoftwareProductList,
+    filteredItems
 }) => {
     const fullSoftwareProducts = softwareProductList
         .filter(
@@ -50,6 +51,23 @@ export const mapStateToProps = ({
         return accum;
     };
 
+    const reduceFilteredLicenseModelList = (accum, vlm) => {
+        let currentSoftwareProductList = sortByStringProperty(
+            filteredItems.vspList.filter(vsp => vsp.vendorId === vlm.id),
+            'name'
+        );
+        accum.push({ ...vlm, softwareProductList: currentSoftwareProductList });
+        return accum;
+    };
+
+    const updatedFilteredItems = {
+        vspList: [...filteredItems.vspList],
+        vlmList: sortByStringProperty(
+            filteredItems.vlmList.reduce(reduceFilteredLicenseModelList, []),
+            'name'
+        )
+    };
+
     licenseModelList = sortByStringProperty(
         licenseModelList.reduce(reduceLicenseModelList, []),
         'name'
@@ -72,7 +90,7 @@ export const mapStateToProps = ({
     } = onboardingCatalog;
     if (filter.byVendorView) {
         catalogActiveTab = tabsMapping.BY_VENDOR;
-    } else if (filter.itemsType && filter.itemsType === itemsType.ARCHIVED) {
+    } else if (filter.itemStatus && filter.itemStatus === itemStatus.ARCHIVED) {
         catalogActiveTab = tabsMapping.ARCHIVE;
     }
 
@@ -89,7 +107,8 @@ export const mapStateToProps = ({
         searchValue,
         vspOverlay,
         selectedVendor,
-        users: users.usersList
+        users: users.usersList,
+        filteredItems: updatedFilteredItems
     };
 };
 
index 87ec2d1..2826e32 100644 (file)
@@ -1,25 +1,30 @@
-/*!
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+/*
+ * Copyright © 2016-2018 European Support Limited
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing
- * permissions and limitations under the License.
+ * 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 { tabsMapping, actionTypes } from './OnboardConstants.js';
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
 import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import VersionsPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
-import { catalogItemStatuses } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
+
 import { itemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
 import PermissionsActionHelper from 'sdc-app/onboarding/permissions/PermissionsActionHelper.js';
+import { actionTypes as filterActionTypes } from './filter/FilterConstants.js';
+import {
+    versionStatus,
+    itemStatus
+} from 'sdc-app/common/helpers/ItemsHelperConstants.js';
 
 const OnboardActionHelper = {
     resetOnboardStore(dispatch) {
@@ -33,6 +38,18 @@ const OnboardActionHelper = {
             type: actionTypes.CHANGE_ACTIVE_ONBOARD_TAB,
             activeTab
         });
+        dispatch({
+            type: filterActionTypes.FILTER_DATA_CHANGED,
+            deltaData:
+                activeTab === tabsMapping.WORKSPACE
+                    ? {
+                          versionStatus: versionStatus.DRAFT,
+                          itemStatus: itemStatus.ACTIVE
+                      }
+                    : {
+                          versionStatus: versionStatus.CERTIFIED
+                      }
+        });
     },
     changeSearchValue(dispatch, searchValue) {
         dispatch({
@@ -54,7 +71,7 @@ const OnboardActionHelper = {
                 itemType: itemTypes.LICENSE_MODEL
             }).then(({ results }) => {
                 results = results.filter(
-                    version => version.status === catalogItemStatuses.DRAFT
+                    version => version.status === versionStatus.DRAFT
                 );
                 if (results.length !== 1) {
                     ScreensHelper.loadScreen(dispatch, {
@@ -104,7 +121,7 @@ const OnboardActionHelper = {
                 itemType: itemTypes.SOFTWARE_PRODUCT
             }).then(({ results }) => {
                 results = results.filter(
-                    version => version.status === catalogItemStatuses.DRAFT
+                    version => version.status === versionStatus.DRAFT
                 );
                 if (results.length !== 1) {
                     ScreensHelper.loadScreen(dispatch, {
index dcaeaa7..0fc64b3 100644 (file)
@@ -16,7 +16,9 @@
 import React from 'react';
 import PropTypes from 'prop-types';
 import OnboardingCatalogView from './onboardingCatalog/OnboardingCatalogView.jsx';
+import OnboardingCatalogViewWithFilter from './onboardingCatalog/OnboardingCatalogViewWithFilter.jsx';
 import WorkspaceView from './workspace/WorkspaceView.jsx';
+import WorkspaceViewWithFilter from './workspace/WorkspaceViewWithFilter.jsx';
 import { tabsMapping } from './OnboardConstants.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
 import classnames from 'classnames';
@@ -25,7 +27,8 @@ import objectValues from 'lodash/values.js';
 import { catalogItemTypes } from './onboardingCatalog/OnboardingCatalogConstants.js';
 import NotificationsView from 'sdc-app/onboarding/userNotifications/NotificationsView.jsx';
 import Filter from 'sdc-app/onboarding/onboard/filter/Filter.jsx';
-
+import featureToggle from 'sdc-app/features/featureToggle.js';
+import { featureToggleNames } from 'sdc-app/features/FeaturesConstants.js';
 const OnboardHeaderTabs = ({ onTabClick, activeTab }) => (
     <div className="onboard-header-tabs">
         <div
@@ -47,6 +50,16 @@ const OnboardHeaderTabs = ({ onTabClick, activeTab }) => (
     </div>
 );
 
+const ToggledOnboardingCatalogView = featureToggle(featureToggleNames.FILTER)({
+    OnComp: OnboardingCatalogViewWithFilter,
+    OffComp: OnboardingCatalogView
+});
+
+const ToggledWorkspaceView = featureToggle(featureToggleNames.FILTER)({
+    OnComp: WorkspaceViewWithFilter,
+    OffComp: WorkspaceView
+});
+
 const OnboardHeader = ({ onSearch, activeTab, onTabClick, searchValue }) => (
     <div className="onboard-header">
         <OnboardHeaderTabs activeTab={activeTab} onTabClick={onTabClick} />
@@ -85,11 +98,11 @@ class OnboardView extends React.Component {
     renderViewByTab(activeTab) {
         switch (activeTab) {
             case tabsMapping.WORKSPACE:
-                return <WorkspaceView {...this.props} />;
+                return <ToggledWorkspaceView {...this.props} />;
             case tabsMapping.CATALOG:
-                return <OnboardingCatalogView {...this.props} />;
+                return <ToggledOnboardingCatalogView {...this.props} />;
             default:
-                return <WorkspaceView {...this.props} />;
+                return <ToggledWorkspaceView {...this.props} />;
         }
     }
 
index c80232d..a00357c 100644 (file)
 import { connect } from 'react-redux';
 import React from 'react';
 import PropTypes from 'prop-types';
-import i18n from 'nfvo-utils/i18n/i18n.js';
-import Input from 'nfvo-components/input/validation/Input.jsx';
-import Accordion from 'nfvo-components/accordion/Accordion.jsx';
-import { actionTypes } from './FilterConstants.js';
 import featureToggle from 'sdc-app/features/featureToggle.js';
 import { featureToggleNames } from 'sdc-app/features/FeaturesConstants.js';
 import { tabsMapping as onboardTabsMapping } from '../OnboardConstants.js';
-import { itemsType as itemsTypeConstants } from './FilterConstants.js';
+import { actionTypes } from './FilterConstants.js';
+
+import Panel from 'sdc-ui/lib/react/Panel.js';
+import {
+    ItemStatus,
+    ByVendorView,
+    EntityType,
+    Permissions,
+    OnboardingProcedure
+} from './FilterComponents.jsx';
 
 const mapStateToProps = ({ onboard: { filter, activeTab } }) => {
     return {
@@ -35,145 +40,39 @@ const mapStateToProps = ({ onboard: { filter, activeTab } }) => {
 
 const mapActionsToProps = dispatch => {
     return {
-        onDataChanged: deltaData =>
+        onDataChanged: deltaData => {
             dispatch({
                 type: actionTypes.FILTER_DATA_CHANGED,
                 deltaData
-            })
+            });
+        }
     };
 };
 
-const Filter = ({
-    onDataChanged,
-    data: {
-        entityTypeVsp,
-        entityTypeVlm,
-        roleOwner,
-        roleContributor,
-        roleViewer,
-        procedureNetwork,
-        procedureManual,
-        recentlyUpdated,
-        byVendorView,
-        itemsType
-    },
-    activeTab
-}) => (
-    <div className="catalog-filter">
-        {activeTab === onboardTabsMapping.CATALOG && (
-            <Input
-                type="select"
-                className="catalog-filter-items-type"
-                data-test-id="catalog-filter-items-type"
-                disabled={byVendorView}
-                value={itemsType}
-                onChange={e => onDataChanged({ itemsType: e.target.value })}>
-                <option
-                    key={itemsTypeConstants.ACTIVE}
-                    value={itemsTypeConstants.ACTIVE}>
-                    Active Items
-                </option>
-                <option
-                    key={itemsTypeConstants.ARCHIVED}
-                    value={itemsTypeConstants.ARCHIVED}>
-                    Archived Items
-                </option>
-            </Input>
-        )}
-        {activeTab === onboardTabsMapping.CATALOG && (
-            <Input
-                label={i18n('By Vendor View')}
-                type="checkbox"
-                disabled={itemsType === itemsTypeConstants.ARCHIVED}
-                checked={byVendorView}
-                onChange={byVendorView => onDataChanged({ byVendorView })}
-                data-test-id="filter-by-vendor-view"
-                value=""
-            />
-        )}
-        <Input
-            label={i18n('Recently Updated')}
-            type="checkbox"
-            checked={recentlyUpdated}
-            onChange={recentlyUpdated => onDataChanged({ recentlyUpdated })}
-            data-test-id="filter-recently-updated"
-            value=""
-        />
-
-        <Accordion title={i18n('ENTITY TYPE')}>
-            <Input
-                label={i18n('VSP')}
-                type="checkbox"
-                checked={entityTypeVsp}
-                onChange={entityTypeVsp => onDataChanged({ entityTypeVsp })}
-                data-test-id="filter-type-vsp"
-                value=""
-            />
-            <Input
-                label={i18n('VLM')}
-                type="checkbox"
-                checked={entityTypeVlm}
-                onChange={entityTypeVlm => onDataChanged({ entityTypeVlm })}
-                data-test-id="filter-type-vlm"
-                value=""
-            />
-        </Accordion>
-
-        <Accordion title={i18n('ROLE')}>
-            <Input
-                label={i18n('Owner')}
-                type="checkbox"
-                checked={roleOwner}
-                onChange={roleOwner => onDataChanged({ roleOwner })}
-                data-test-id="filter-role-owner"
-                value=""
-            />
-            <Input
-                label={i18n('Contributer')}
-                type="checkbox"
-                checked={roleContributor}
-                onChange={roleContributor => onDataChanged({ roleContributor })}
-                data-test-id="filter-role-contributor"
-                value=""
-            />
-            <Input
-                label={i18n('Viewer')}
-                type="checkbox"
-                checked={roleViewer}
-                onChange={roleViewer => onDataChanged({ roleViewer })}
-                data-test-id="filter-role-viewr"
-                value=""
-            />
-        </Accordion>
-
-        <Accordion title={i18n('ONBOARDING PROCEDURE')}>
-            <Input
-                label={i18n('Network Package')}
-                type="checkbox"
-                checked={procedureNetwork}
-                onChange={procedureNetwork =>
-                    onDataChanged({ procedureNetwork })
-                }
-                data-test-id="filter-procedure-network"
-                value=""
-            />
-            <Input
-                label={i18n('Manual')}
-                type="checkbox"
-                checked={procedureManual}
-                onChange={procedureManual => onDataChanged({ procedureManual })}
-                data-test-id="filter-procedure-manual"
-                value=""
-            />
-        </Accordion>
-    </div>
-);
+const Filter = ({ onDataChanged, data, activeTab }) => {
+    return (
+        <Panel className="catalog-filter">
+            <ItemStatus data={data} onDataChanged={onDataChanged} />
+            <EntityType data={data} onDataChanged={onDataChanged} />
+            <Permissions data={data} onDataChanged={onDataChanged} />
+            <OnboardingProcedure data={data} onDataChanged={onDataChanged} />
+            {activeTab === onboardTabsMapping.CATALOG && (
+                <ByVendorView data={data} onDataChanged={onDataChanged} />
+            )}
+        </Panel>
+    );
+};
 
 Filter.PropTypes = {
     onDataChanged: PropTypes.func,
-    data: PropTypes.object
+    data: PropTypes.object,
+    activeTab: PropTypes.number
 };
 
 export default featureToggle(featureToggleNames.FILTER)(
     connect(mapStateToProps, mapActionsToProps)(Filter)
 );
+
+export const ConnectedFilter = connect(mapStateToProps, mapActionsToProps)(
+    Filter
+);
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterActionHelper.js
new file mode 100644 (file)
index 0000000..f8155df
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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 { default as ItemsHelper } from 'sdc-app/common/helpers/ItemsHelper.js';
+import {
+    itemType,
+    versionStatus
+} from 'sdc-app/common/helpers/ItemsHelperConstants.js';
+import { actionTypes } from './FilterConstants.js';
+
+const FilterActionHelper = {
+    async updateFilteredItems(dispatch, filter) {
+        let permission = { ...filter.permission };
+        if (
+            filter.versionStatus === versionStatus.DRAFT &&
+            !permission.Owner &&
+            !permission.Contributor
+        ) {
+            permission.Owner = true;
+            permission.Contributor = true;
+        }
+        const items = await ItemsHelper.fetchItems({
+            ...filter,
+            permission
+        });
+        let vspList = [];
+        let vlmList = [];
+        items.results.map(item => {
+            if (item.type === itemType.VSP) {
+                const { properties, ...all } = item;
+                vspList.push({ ...all, ...properties });
+            } else {
+                vlmList.push(item);
+            }
+        });
+
+        dispatch({
+            type: actionTypes.UPDATE_FILTERED_LIST,
+            data: {
+                vspList,
+                vlmList
+            }
+        });
+    }
+};
+
+export default FilterActionHelper;
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterComponents.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterComponents.jsx
new file mode 100644 (file)
index 0000000..65ec733
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import React from 'react';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import { itemStatus } from 'sdc-app/common/helpers/ItemsHelperConstants.js';
+import Accordion from 'sdc-ui/lib/react/Accordion.js';
+import Checklist from 'sdc-ui/lib/react/Checklist.js';
+import Checkbox from 'sdc-ui/lib/react/Checkbox.js';
+
+export const ItemStatus = ({ data, onDataChanged, byVendorView }) => (
+    <Input
+        type="select"
+        className="catalog-filter-items-type"
+        data-test-id="catalog-filter-items-type"
+        disabled={byVendorView}
+        value={data.itemStatus}
+        onChange={e => onDataChanged({ itemStatus: e.target.value }, data)}>
+        <option key={itemStatus.ACTIVE} value={itemStatus.ACTIVE}>
+            {i18n('Active Items')}
+        </option>
+        <option key={itemStatus.ARCHIVED} value={itemStatus.ARCHIVED}>
+            {i18n('Archived Items')}
+        </option>
+    </Input>
+);
+
+const FilterList = ({ title, items, groupKey, onDataChanged, data }) => {
+    let onChange = value => {
+        let obj = {};
+        obj[groupKey] = { ...data[groupKey], ...value };
+        onDataChanged(obj);
+    };
+    return (
+        <Accordion title={title}>
+            <Checklist items={items} onChange={onChange} />
+        </Accordion>
+    );
+};
+
+export const ByVendorView = ({ data, onDataChanged }) => (
+    <Checkbox
+        label={i18n('By Vendor View')}
+        className="catalog-filter-by-vendor-view"
+        disabled={data.itemsType === itemStatus.ARCHIVED}
+        checked={data.byVendorView}
+        onChange={byVendorView => onDataChanged({ byVendorView }, data)}
+        data-test-id="filter-by-vendor-view"
+        value=""
+    />
+);
+
+export const EntityType = ({ data, onDataChanged }) => {
+    const items = [
+        {
+            label: i18n('VSP'),
+            dataTestId: 'catalog-filter-type-vsp',
+            value: 'vsp',
+            checked: data.itemType && data.itemType.vsp
+        },
+        {
+            label: i18n('VLM'),
+            dataTestId: 'catalog-ilter-type-vlm',
+            value: 'vlm',
+            checked: data.itemType && data.itemType.vlm
+        }
+    ];
+    return (
+        <FilterList
+            title={i18n('ENTITY TYPE')}
+            items={items}
+            onDataChanged={onDataChanged}
+            data={data}
+            groupKey="itemType"
+        />
+    );
+};
+
+export const Permissions = ({ data, onDataChanged }) => {
+    const items = [
+        {
+            label: i18n('Owner'),
+            dataTestId: 'catalog-filter-permission-owner',
+            value: 'Owner',
+            checked: data.permission && data.permission.Owner
+        },
+        {
+            label: i18n('Contributor'),
+            dataTestId: 'catalog-filter-permission-contributor',
+            value: 'Contributor',
+            checked: data.permission && data.permission.Contributor
+        }
+    ];
+
+    return (
+        <FilterList
+            title={i18n('PERMISSIONS')}
+            items={items}
+            onDataChanged={onDataChanged}
+            data={data}
+            groupKey="permission"
+        />
+    );
+};
+
+export const OnboardingProcedure = ({ data, onDataChanged }) => {
+    const items = [
+        {
+            label: i18n('Network Package'),
+            dataTestId: 'catalog-filter-procedure-network',
+            value: 'NetworkPackage',
+            checked:
+                data.onboardingMethod && data.onboardingMethod.NetworkPackage
+        },
+        {
+            label: i18n('Manual'),
+            dataTestId: 'catalog-filter-procedure-manual',
+            value: 'Manual',
+            checked: data.onboardingMethod && data.onboardingMethod.Manual
+        }
+    ];
+
+    return (
+        <FilterList
+            title={i18n('ONBOARDING PROCEDURE')}
+            items={items}
+            onDataChanged={onDataChanged}
+            data={data}
+            groupKey="onboardingMethod"
+        />
+    );
+};
index edfe592..9dce52d 100644 (file)
 import keyMirror from 'nfvo-utils/KeyMirror.js';
 
 export const actionTypes = keyMirror({
-    FILTER_DATA_CHANGED: null
+    FILTER_DATA_CHANGED: null,
+    UPDATE_FILTERED_LIST: null
 });
-
-export const itemsType = {
-    ACTIVE: '1',
-    ARCHIVED: '2'
-};
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterMiddleware.js b/openecomp-ui/src/sdc-app/onboarding/onboard/filter/FilterMiddleware.js
new file mode 100644 (file)
index 0000000..8490bfe
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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 FilterActionHelper from './FilterActionHelper.js';
+import { actionTypes } from './FilterConstants.js';
+
+const filterUpdater = store => next => action => {
+    if (action.type === actionTypes.FILTER_DATA_CHANGED) {
+        const filter = store.getState().onboard.filter;
+
+        FilterActionHelper.updateFilteredItems(store.dispatch, {
+            ...filter,
+            ...action.deltaData
+        });
+    }
+    return next(action);
+};
+
+export default filterUpdater;
index f1e8574..28b3475 100644 (file)
  * limitations under the License.
  */
 import { actionTypes } from './FilterConstants.js';
+import {
+    itemStatus,
+    versionStatus
+} from 'sdc-app/common/helpers/ItemsHelperConstants.js';
 
-export default (state = {}, action) => {
+const defaultState = {
+    itemStatus: itemStatus.ACTIVE,
+    versionStatus: versionStatus.DRAFT,
+    entityType: {},
+    permission: {},
+    onboardingMethod: {}
+};
+export default (state = defaultState, action) => {
     switch (action.type) {
         case actionTypes.FILTER_DATA_CHANGED:
             return {
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/filter/ItemsReducer.js b/openecomp-ui/src/sdc-app/onboarding/onboard/filter/ItemsReducer.js
new file mode 100644 (file)
index 0000000..fa1528d
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+import { actionTypes } from './FilterConstants.js';
+export default (state = { vspList: [], vlmList: [] }, action) => {
+    switch (action.type) {
+        case actionTypes.UPDATE_FILTERED_LIST:
+            return action.data;
+        default:
+            return state;
+    }
+};
index 2cc32c2..a416d36 100644 (file)
@@ -83,8 +83,8 @@ const FilterCatalogHeader = () => (
 );
 
 const FeaturedCatalogHeader = featureToggle(featureToggleNames.FILTER)({
-    AComp: FilterCatalogHeader,
-    BComp: CatalogHeader
+    OnComp: FilterCatalogHeader,
+    OffComp: CatalogHeader
 });
 
 class OnboardingCatalogView extends React.Component {
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogViewWithFilter.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogViewWithFilter.jsx
new file mode 100644 (file)
index 0000000..86c437d
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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 DetailsCatalogView from 'sdc-app/onboarding/onboard/DetailsCatalogView.jsx';
+import VendorCatalogView from './VendorCatalogView.jsx';
+import { tabsMapping } from './OnboardingCatalogConstants.js';
+import { tabsMapping as WCTabsMapping } from 'sdc-app/onboarding/onboard/OnboardConstants.js';
+
+const CatalogHeader = () => (
+    <div className="catalog-header">
+        <div className="catalog-header-tabs">
+            <div className="catalog-header-tab active">
+                {i18n('ONBOARD CATALOG')}
+            </div>
+        </div>
+    </div>
+);
+
+class OnboardingCatalogView extends React.Component {
+    renderViewByTab(activeTab) {
+        const {
+            users,
+            vspOverlay,
+            onSelectLicenseModel,
+            onSelectSoftwareProduct,
+            onAddLicenseModelClick,
+            onAddSoftwareProductClick,
+            onVspOverlayChange,
+            onVendorSelect,
+            selectedVendor,
+            searchValue,
+            onMigrate,
+            filteredItems
+        } = this.props;
+
+        const { vlmList, vspList } = filteredItems;
+
+        switch (activeTab) {
+            case tabsMapping.ARCHIVE:
+                return (
+                    <DetailsCatalogView
+                        VLMList={vlmList}
+                        VSPList={vspList}
+                        users={users}
+                        onSelectVLM={(item, users) =>
+                            onSelectLicenseModel(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        onSelectVSP={(item, users) =>
+                            onSelectSoftwareProduct(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        filter={searchValue}
+                        onMigrate={onMigrate}
+                    />
+                );
+            case tabsMapping.ACTIVE:
+                return (
+                    <DetailsCatalogView
+                        VLMList={vlmList}
+                        VSPList={vspList}
+                        users={users}
+                        onAddVLM={onAddLicenseModelClick}
+                        onAddVSP={onAddSoftwareProductClick}
+                        onSelectVLM={(item, users) =>
+                            onSelectLicenseModel(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        onSelectVSP={(item, users) =>
+                            onSelectSoftwareProduct(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        filter={searchValue}
+                        onMigrate={onMigrate}
+                    />
+                );
+            case tabsMapping.BY_VENDOR:
+            default:
+                return (
+                    <VendorCatalogView
+                        licenseModelList={vlmList}
+                        users={users}
+                        onAddVSP={onAddSoftwareProductClick}
+                        onAddVLM={onAddLicenseModelClick}
+                        onSelectVSP={(item, users) =>
+                            onSelectSoftwareProduct(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        onSelectVLM={(item, users) =>
+                            onSelectLicenseModel(
+                                item,
+                                users,
+                                WCTabsMapping.CATALOG
+                            )
+                        }
+                        vspOverlay={vspOverlay}
+                        onVendorSelect={onVendorSelect}
+                        selectedVendor={selectedVendor}
+                        onVspOverlayChange={onVspOverlayChange}
+                        onMigrate={onMigrate}
+                        filter={searchValue}
+                    />
+                );
+        }
+    }
+
+    render() {
+        const { selectedVendor, catalogActiveTab: activeTab } = this.props;
+        return (
+            <div className="catalog-wrapper">
+                {!selectedVendor && <CatalogHeader />}
+                {this.renderViewByTab(activeTab)}
+            </div>
+        );
+    }
+}
+
+export default OnboardingCatalogView;
index bef47d5..12beff7 100644 (file)
@@ -60,8 +60,8 @@ class VendorItem extends React.Component {
                     </TileInfoLine>
                     <TileInfoLine>
                         <Button
-                            btnType="outline-rounded"
-                            color="dark-gray"
+                            btnType="secondary"
+                            className="venodor-tile-btn"
                             onClick={e => this.handleVspCountClick(e)}
                             data-test-id="catalog-vsp-count"
                             disabled={!softwareProductList.length}>
diff --git a/openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceViewWithFilter.jsx b/openecomp-ui/src/sdc-app/onboarding/onboard/workspace/WorkspaceViewWithFilter.jsx
new file mode 100644 (file)
index 0000000..eec5962
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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 DetailsCatalogView from '../DetailsCatalogView.jsx';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import { tabsMapping } from 'sdc-app/onboarding/onboard/OnboardConstants.js';
+
+const WorkspaceView = props => {
+    let {
+        onAddLicenseModelClick,
+        users,
+        onAddSoftwareProductClick,
+        onSelectLicenseModel,
+        onSelectSoftwareProduct,
+        searchValue,
+        onMigrate,
+        filteredItems: { vspList, vlmList }
+    } = props;
+
+    return (
+        <div className="catalog-wrapper workspace-view">
+            <div className="catalog-header workspace-header">
+                {i18n('WORKSPACE')}
+            </div>
+            <DetailsCatalogView
+                VLMList={vlmList}
+                VSPList={vspList}
+                users={users}
+                onAddVLM={onAddLicenseModelClick}
+                onAddVSP={onAddSoftwareProductClick}
+                onSelectVLM={(item, users) =>
+                    onSelectLicenseModel(item, users, tabsMapping.WORKSPACE)
+                }
+                onSelectVSP={(item, users) =>
+                    onSelectSoftwareProduct(item, users, tabsMapping.WORKSPACE)
+                }
+                onMigrate={onMigrate}
+                filter={searchValue}
+            />
+        </div>
+    );
+};
+
+export default WorkspaceView;
index 4a2d7a2..25bd32e 100644 (file)
@@ -45,8 +45,11 @@ import { CommitModalType } from 'nfvo-components/panel/versionController/compone
 import { actionTypes as commonActionTypes } from 'sdc-app/common/reducers/PlainDataReducerConstants.js';
 import versionPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
 import { itemTypes } from 'sdc-app/onboarding/versionsPage/VersionsPageConstants.js';
-import { catalogItemStatuses } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
 import getValue from 'nfvo-utils/getValue.js';
+import {
+    itemStatus,
+    versionStatus
+} from 'sdc-app/common/helpers/ItemsHelperConstants.js';
 
 function getLicensingData(licensingData = {}) {
     const { licenseAgreement, featureGroups } = licensingData;
@@ -112,19 +115,17 @@ function putSoftwareProductAction(id, action, version) {
 
 function fetchSoftwareProductList() {
     return RestAPIUtil.fetch(
-        `${baseUrl()}?versionFilter=${catalogItemStatuses.DRAFT}`
+        `${baseUrl()}?versionFilter=${versionStatus.DRAFT}`
     );
 }
 
 function fetchArchivedSoftwareProductList() {
-    return RestAPIUtil.fetch(
-        `${baseUrl()}?Status=${catalogItemStatuses.ARCHIVED}`
-    );
+    return RestAPIUtil.fetch(`${baseUrl()}?Status=${itemStatus.ARCHIVED}`);
 }
 
 function fetchFinalizedSoftwareProductList() {
     return RestAPIUtil.fetch(
-        `${baseUrl()}?versionFilter=${catalogItemStatuses.CERTIFIED}`
+        `${baseUrl()}?versionFilter=${versionStatus.CERTIFIED}`
     );
 }
 
@@ -664,9 +665,8 @@ const SoftwareProductActionHelper = {
             version
         }).then(({ inMerge, isDirty, updatedVersion }) => {
             if (
-                (updatedVersion.status === catalogItemStatuses.CERTIFIED ||
-                    updatedVersion.archivedStatus ===
-                        catalogItemStatuses.ARCHIVED) &&
+                (updatedVersion.status === versionStatus.CERTIFIED ||
+                    updatedVersion.archivedStatus === itemStatus.ARCHIVED) &&
                 (action === VersionControllerActionsEnum.COMMIT ||
                     action === VersionControllerActionsEnum.SYNC)
             ) {
@@ -675,8 +675,7 @@ const SoftwareProductActionHelper = {
                     itemId: softwareProductId
                 });
                 const msg =
-                    updatedVersion.archivedStatus ===
-                    catalogItemStatuses.ARCHIVED
+                    updatedVersion.archivedStatus === itemStatus.ARCHIVED
                         ? i18n('Item was Archived')
                         : i18n('Item version already Certified');
                 dispatch({
index 41584d9..9a7d257 100644 (file)
  * permissions and limitations under the License.
  */
 import { connect } from 'react-redux';
-
+import featureToggle from 'sdc-app/features/featureToggle.js';
+import { featureToggleNames } from 'sdc-app/features/FeaturesConstants.js';
 import SoftwareProductCreationActionHelper from './SoftwareProductCreationActionHelper.js';
 import SoftwareProductCreationView from './SoftwareProductCreationView.jsx';
+import SoftwareProductCreationViewWithFilter from './SoftwareProductCreationViewWithFilter.jsx';
 import ValidationHelper from 'sdc-app/common/helpers/ValidationHelper.js';
 import SoftwareProductActionHelper from '../SoftwareProductActionHelper.js';
 import VersionsPageActionHelper from 'sdc-app/onboarding/versionsPage/VersionsPageActionHelper.js';
@@ -24,6 +26,16 @@ import { itemTypes as versionItemTypes } from 'sdc-app/onboarding/versionsPage/V
 import ScreensHelper from 'sdc-app/common/helpers/ScreensHelper.js';
 import { enums, screenTypes } from 'sdc-app/onboarding/OnboardingConstants.js';
 import PermissionsActionHelper from 'sdc-app/onboarding/permissions/PermissionsActionHelper.js';
+import UniqueTypesHelper from 'sdc-app/common/helpers/UniqueTypesHelper.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import { itemType } from 'sdc-app/common/helpers/ItemsHelperConstants.js';
+
+const ToggledSoftwareProductCreationView = featureToggle(
+    featureToggleNames.FILTER
+)({
+    OnComp: SoftwareProductCreationViewWithFilter,
+    OffComp: SoftwareProductCreationView
+});
 
 export const mapStateToProps = ({
     finalizedLicenseModelList,
@@ -33,7 +45,7 @@ export const mapStateToProps = ({
     finalizedSoftwareProductList,
     softwareProduct: { softwareProductCreation, softwareProductCategories }
 }) => {
-    let { genericFieldInfo } = softwareProductCreation;
+    let { genericFieldInfo, vendorList = [] } = softwareProductCreation;
     let isFormValid = ValidationHelper.checkFormValid(genericFieldInfo);
 
     let VSPNames = {};
@@ -52,6 +64,7 @@ export const mapStateToProps = ({
         disableVendor: softwareProductCreation.disableVendor,
         softwareProductCategories,
         finalizedLicenseModelList,
+        vendorList,
         isFormValid,
         formReady: softwareProductCreation.formReady,
         genericFieldInfo,
@@ -99,10 +112,22 @@ export const mapActionsToProps = dispatch => {
             });
         },
         onValidateForm: formName =>
-            ValidationHelper.validateForm(dispatch, formName)
+            ValidationHelper.validateForm(dispatch, formName),
+        isNameUnique: (value, name, formName) =>
+            UniqueTypesHelper.isNameUnique(dispatch, {
+                value,
+                name,
+                formName,
+                errorText: `${i18n(
+                    'Software product by the name'
+                )} ${value} ${i18n('already exists')}. ${i18n(
+                    'Software product name must be unique'
+                )}`,
+                itemType: itemType.VSP
+            })
     };
 };
 
 export default connect(mapStateToProps, mapActionsToProps, null, {
     withRef: true
-})(SoftwareProductCreationView);
+})(ToggledSoftwareProductCreationView);
index 1b1fd71..259b50b 100644 (file)
@@ -24,7 +24,11 @@ import {
 import { modalContentMapper } from 'sdc-app/common/modal/ModalContentMapper.js';
 import { actionTypes } from './SoftwareProductCreationConstants.js';
 import i18n from 'nfvo-utils/i18n/i18n.js';
-
+import ItemsHelper from 'sdc-app/common/helpers/ItemsHelper.js';
+import {
+    itemStatus,
+    versionStatus
+} from 'sdc-app/common/helpers/ItemsHelperConstants.js';
 function baseUrl() {
     const restPrefix = Configuration.get('restPrefix');
     return `${restPrefix}/v1.0/vendor-software-products/`;
@@ -45,7 +49,7 @@ const SoftwareProductCreationActionHelper = {
             type: actionTypes.OPEN,
             selectedVendorId: vendorId
         });
-
+        this.loadVendorList(dispatch);
         dispatch({
             type: modalActionTypes.GLOBAL_MODAL_SHOW,
             data: {
@@ -78,6 +82,19 @@ const SoftwareProductCreationActionHelper = {
             });
             return result;
         });
+    },
+    async loadVendorList(dispatch) {
+        const { results } = await ItemsHelper.fetchItems({
+            itemStatus: itemStatus.ACTIVE,
+            versionStatus: versionStatus.CERTIFIED,
+            itemType: {
+                vlm: true
+            }
+        });
+        dispatch({
+            type: actionTypes.VENDOR_LIST_LOADED,
+            vendorList: results
+        });
     }
 };
 
index ad10346..128b3ed 100644 (file)
@@ -18,7 +18,8 @@ import keyMirror from 'nfvo-utils/KeyMirror.js';
 export const actionTypes = keyMirror({
     OPEN: null,
     RESET_DATA: null,
-    SOFTWARE_PRODUCT_CREATED: null
+    SOFTWARE_PRODUCT_CREATED: null,
+    VENDOR_LIST_LOADED: null
 });
 
 export const SP_CREATION_FORM_NAME = 'SPCREATIONFORM';
index 5f70f18..b019248 100644 (file)
@@ -74,6 +74,11 @@ export default (state = {}, action) => {
                 },
                 showModal: true
             };
+        case actionTypes.VENDOR_LIST_LOADED:
+            return {
+                ...state,
+                vendorList: action.vendorList
+            };
         case actionTypes.RESET_DATA:
             return {};
         default:
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationViewWithFilter.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/creation/SoftwareProductCreationViewWithFilter.jsx
new file mode 100644 (file)
index 0000000..810337d
--- /dev/null
@@ -0,0 +1,329 @@
+/*!
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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 PropTypes from 'prop-types';
+import i18n from 'nfvo-utils/i18n/i18n.js';
+import Validator from 'nfvo-utils/Validator.js';
+import Input from 'nfvo-components/input/validation/Input.jsx';
+import Form from 'nfvo-components/input/validation/Form.jsx';
+import GridSection from 'nfvo-components/grid/GridSection.jsx';
+import GridItem from 'nfvo-components/grid/GridItem.jsx';
+
+import { SP_CREATION_FORM_NAME } from './SoftwareProductCreationConstants.js';
+import sortByStringProperty from 'nfvo-utils/sortByStringProperty.js';
+
+import SoftwareProductCategoriesHelper from 'sdc-app/onboarding/softwareProduct/SoftwareProductCategoriesHelper.js';
+import { onboardingMethod as onboardingMethodConst } from '../SoftwareProductConstants.js';
+
+const SoftwareProductPropType = PropTypes.shape({
+    id: PropTypes.string,
+    name: PropTypes.string,
+    description: PropTypes.string,
+    category: PropTypes.string,
+    subCategory: PropTypes.string,
+    vendorId: PropTypes.string
+});
+
+class SoftwareProductCreationView extends React.Component {
+    static propTypes = {
+        data: SoftwareProductPropType,
+        finalizedLicenseModelList: PropTypes.array,
+        softwareProductCategories: PropTypes.array,
+        VSPNames: PropTypes.object,
+        usersList: PropTypes.array,
+        onDataChanged: PropTypes.func.isRequired,
+        onSubmit: PropTypes.func.isRequired,
+        onCancel: PropTypes.func.isRequired
+    };
+
+    render() {
+        let {
+            softwareProductCategories,
+            data = {},
+            onDataChanged,
+            onCancel,
+            genericFieldInfo,
+            disableVendor
+        } = this.props;
+        let {
+            name,
+            description,
+            vendorId,
+            subCategory,
+            onboardingMethod
+        } = data;
+
+        const vendorList = this.getVendorList();
+        return (
+            <div className="software-product-creation-page">
+                {genericFieldInfo && (
+                    <Form
+                        ref={validationForm =>
+                            (this.validationForm = validationForm)
+                        }
+                        hasButtons={true}
+                        onSubmit={() => this.submit()}
+                        onReset={() => onCancel()}
+                        labledButtons={true}
+                        isValid={this.props.isFormValid}
+                        submitButtonText={i18n('Create')}
+                        formReady={this.props.formReady}
+                        onValidateForm={() => this.validate()}>
+                        <GridSection hasLastColSet>
+                            <GridItem colSpan="2">
+                                <Input
+                                    value={name}
+                                    label={i18n('Name')}
+                                    isRequired={true}
+                                    onChange={name =>
+                                        onDataChanged(
+                                            { name },
+                                            SP_CREATION_FORM_NAME
+                                        )
+                                    }
+                                    onBlur={this.validateIsNameUnique}
+                                    isValid={genericFieldInfo.name.isValid}
+                                    errorText={genericFieldInfo.name.errorText}
+                                    type="text"
+                                    className="field-section"
+                                    data-test-id="new-vsp-name"
+                                />
+                                <Input
+                                    label={i18n('Vendor')}
+                                    type="select"
+                                    value={vendorId}
+                                    overlayPos="bottom"
+                                    isRequired={true}
+                                    disabled={disableVendor}
+                                    onChange={e => this.onSelectVendor(e)}
+                                    isValid={genericFieldInfo.vendorId.isValid}
+                                    errorText={
+                                        genericFieldInfo.vendorId.errorText
+                                    }
+                                    className="input-options-select"
+                                    groupClassName="bootstrap-input-options"
+                                    data-test-id="new-vsp-vendor">
+                                    {vendorList.map(vendor => (
+                                        <option
+                                            key={vendor.title}
+                                            value={vendor.enum}>
+                                            {vendor.title}
+                                        </option>
+                                    ))}
+                                </Input>
+                                <Input
+                                    label={i18n('Category')}
+                                    type="select"
+                                    value={subCategory}
+                                    isRequired={true}
+                                    onChange={e => this.onSelectSubCategory(e)}
+                                    isValid={
+                                        genericFieldInfo.subCategory.isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo.subCategory.errorText
+                                    }
+                                    className="input-options-select"
+                                    groupClassName="bootstrap-input-options"
+                                    data-test-id="new-vsp-category">
+                                    <option key="" value="">
+                                        {i18n('please select…')}
+                                    </option>
+                                    {softwareProductCategories.map(
+                                        category =>
+                                            category.subcategories && (
+                                                <optgroup
+                                                    key={category.name}
+                                                    label={category.name}>
+                                                    {category.subcategories.map(
+                                                        sub => (
+                                                            <option
+                                                                key={
+                                                                    sub.uniqueId
+                                                                }
+                                                                value={
+                                                                    sub.uniqueId
+                                                                }>{`${
+                                                                sub.name
+                                                            } (${
+                                                                category.name
+                                                            })`}</option>
+                                                        )
+                                                    )}
+                                                </optgroup>
+                                            )
+                                    )}
+                                </Input>
+                            </GridItem>
+                            <GridItem colSpan="2" stretch lastColInRow>
+                                <Input
+                                    value={description}
+                                    label={i18n('Description')}
+                                    isRequired={true}
+                                    overlayPos="bottom"
+                                    onChange={description =>
+                                        onDataChanged(
+                                            { description },
+                                            SP_CREATION_FORM_NAME
+                                        )
+                                    }
+                                    isValid={
+                                        genericFieldInfo.description.isValid
+                                    }
+                                    errorText={
+                                        genericFieldInfo.description.errorText
+                                    }
+                                    type="textarea"
+                                    className="field-section"
+                                    data-test-id="new-vsp-description"
+                                />
+                            </GridItem>
+                        </GridSection>
+                        <OnboardingProcedure
+                            genericFieldInfo={genericFieldInfo}
+                            onboardingMethod={onboardingMethod}
+                            onDataChanged={onDataChanged}
+                        />
+                    </Form>
+                )}
+            </div>
+        );
+    }
+
+    getVendorList() {
+        let { vendorList } = this.props;
+
+        return [{ enum: '', title: i18n('please select...') }].concat(
+            sortByStringProperty(vendorList, 'name').map(vendor => {
+                return {
+                    enum: vendor.id,
+                    title: vendor.name
+                };
+            })
+        );
+    }
+
+    onSelectVendor(e) {
+        const selectedIndex = e.target.selectedIndex;
+        const vendorId = e.target.options[selectedIndex].value;
+        this.props.onDataChanged({ vendorId }, SP_CREATION_FORM_NAME);
+    }
+
+    onSelectSubCategory(e) {
+        const selectedIndex = e.target.selectedIndex;
+        const subCategory = e.target.options[selectedIndex].value;
+        let { softwareProductCategories, onDataChanged } = this.props;
+        let category = SoftwareProductCategoriesHelper.getCurrentCategoryOfSubCategory(
+            subCategory,
+            softwareProductCategories
+        );
+        onDataChanged({ category, subCategory }, SP_CREATION_FORM_NAME);
+    }
+
+    submit() {
+        let {
+            data: softwareProduct,
+            finalizedLicenseModelList,
+            usersList
+        } = this.props;
+        softwareProduct.vendorName = finalizedLicenseModelList.find(
+            vendor => vendor.id === softwareProduct.vendorId
+        ).name;
+        this.props.onSubmit(softwareProduct, usersList);
+    }
+
+    validateName(value) {
+        const { data: { id }, VSPNames } = this.props;
+        const isExists = Validator.isItemNameAlreadyExistsInList({
+            itemId: id,
+            itemName: value,
+            list: VSPNames
+        });
+
+        return !isExists
+            ? { isValid: true, errorText: '' }
+            : {
+                  isValid: false,
+                  errorText: i18n(
+                      "Software product by the name '" +
+                          value +
+                          "' already exists. Software product name must be unique"
+                  )
+              };
+    }
+
+    validateIsNameUnique = e => {
+        const value = e.target.value;
+        this.props.isNameUnique(value, 'name', SP_CREATION_FORM_NAME);
+    };
+
+    validate() {
+        this.props.onValidateForm(SP_CREATION_FORM_NAME);
+    }
+}
+
+const OnboardingProcedure = ({
+    onboardingMethod,
+    onDataChanged,
+    genericFieldInfo
+}) => {
+    return (
+        <GridSection title={i18n('Onboarding procedure')}>
+            <GridItem colSpan={4}>
+                <Input
+                    label={i18n('Network Package')}
+                    overlayPos="top"
+                    isValid={genericFieldInfo.onboardingMethod.isValid}
+                    checked={
+                        onboardingMethod ===
+                        onboardingMethodConst.NETWORK_PACKAGE
+                    }
+                    errorText={genericFieldInfo.onboardingMethod.errorText}
+                    onChange={() =>
+                        onDataChanged(
+                            {
+                                onboardingMethod:
+                                    onboardingMethodConst.NETWORK_PACKAGE
+                            },
+                            SP_CREATION_FORM_NAME
+                        )
+                    }
+                    type="radio"
+                    data-test-id="new-vsp-creation-procedure-heat"
+                />
+            </GridItem>
+            <GridItem colSpan={4}>
+                <Input
+                    label={i18n('Manual')}
+                    overlayPos="bottom"
+                    checked={onboardingMethod === onboardingMethodConst.MANUAL}
+                    isValid={genericFieldInfo.onboardingMethod.isValid}
+                    errorText={genericFieldInfo.onboardingMethod.errorText}
+                    onChange={() =>
+                        onDataChanged(
+                            { onboardingMethod: onboardingMethodConst.MANUAL },
+                            SP_CREATION_FORM_NAME
+                        )
+                    }
+                    type="radio"
+                    data-test-id="new-vsp-creation-procedure-manual"
+                />
+            </GridItem>
+        </GridSection>
+    );
+};
+
+export default SoftwareProductCreationView;
diff --git a/openecomp-ui/test-utils/factories/common/ItemsHelperFactory.js b/openecomp-ui/test-utils/factories/common/ItemsHelperFactory.js
new file mode 100644 (file)
index 0000000..cdfd91b
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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 randomstring from 'randomstring';
+import IdMixin from 'test-utils/factories/mixins/IdMixin.js';
+
+export const itemFactory = new Factory()
+    .extend(IdMixin)
+    .option('isArchived', false)
+    .attrs({
+        description: () => randomstring.generate(),
+        name: () => randomstring.generate(),
+        owner: () => randomstring.generate()
+    })
+    .attr('status', ['isArchived'], isArchived => {
+        return isArchived ? 'ARCHIVE' : 'ACTIVE';
+    });
+
+export const vspFactory = new Factory().extend(itemFactory).attrs({
+    type: 'vsp',
+    properties: {
+        onboardingMethod: 'NetworkPackage',
+        vendorId: randomstring.generate(33),
+        vendorName: randomstring.generate()
+    }
+});
+
+export const vlmFactory = new Factory().extend(itemFactory).attrs({
+    type: 'vlm',
+    properties: {}
+});
diff --git a/openecomp-ui/test-utils/factories/onboard/FilterFactories.js b/openecomp-ui/test-utils/factories/onboard/FilterFactories.js
new file mode 100644 (file)
index 0000000..a659c3d
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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';
+
+export const FilterFactory = new Factory().attrs({
+    entityType: {},
+    itemStatus: 'ACTIVE',
+    onboardingMethod: {},
+    permission: {},
+    versionStatus: 'Draft'
+});
index 3228694..92b1255 100644 (file)
@@ -1,23 +1,22 @@
-/*!
- * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+/*
+ * Copyright © 2016-2018 European Support Limited
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
- * or implied. See the License for the specific language governing
- * permissions and limitations under the License.
+ * 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 {storeCreator} from 'sdc-app/AppStore.js';
+import { Factory } from 'rosie';
+import { storeCreator } from 'sdc-app/AppStore.js';
 
 const store = storeCreator();
 const defaultStore = store.getState();
 
-export const OnboardStoreFactory = new Factory()
-       .attrs(defaultStore.onboard);
+export const OnboardStoreFactory = new Factory().attrs(defaultStore.onboard);
diff --git a/openecomp-ui/test/onboard/filter/filter.test.js b/openecomp-ui/test/onboard/filter/filter.test.js
new file mode 100644 (file)
index 0000000..1b89a30
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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 { storeCreator } from 'sdc-app/AppStore.js';
+import mockRest from 'test-utils/MockRest.js';
+import { cloneAndSet } from 'test-utils/Util.js';
+import { actionTypes } from 'sdc-app/onboarding/onboard/filter/FilterConstants.js';
+import {
+    vspFactory,
+    vlmFactory
+} from 'test-utils/factories/common/ItemsHelperFactory.js';
+import { FilterFactory } from 'test-utils/factories/onboard/FilterFactories.js';
+import {
+    itemStatus,
+    versionStatus
+} from 'sdc-app/common/helpers/ItemsHelperConstants.js';
+import OnboardActionHelper from 'sdc-app/onboarding/onboard/OnboardActionHelper.js';
+import { tabsMapping } from 'sdc-app/onboarding/onboard/OnboardConstants.js';
+
+const vsps = vspFactory.buildList(1);
+const vlms = vlmFactory.buildList(1);
+
+const timeoutPromise = new Promise(resolve => {
+    setTimeout(function() {
+        resolve();
+    }, 100);
+});
+
+describe('Onboard Filter Tests', () => {
+    it('basic test', done => {
+        const store = storeCreator();
+
+        mockRest.addHandler('fetch', ({ data, options, baseUrl }) => {
+            expect(baseUrl).toEqual(
+                `/onboarding-api/v1.0/items?&itemStatus=${
+                    itemStatus.ACTIVE
+                }&versionStatus=${versionStatus.DRAFT}`
+            );
+            expect(data).toEqual(undefined);
+            expect(options).toEqual(undefined);
+            return { results: [] };
+        });
+        const expectedStore = store.getState();
+        store.dispatch({
+            type: actionTypes.FILTER_DATA_CHANGED,
+            deltaData: {}
+        });
+        return timeoutPromise.then(function() {
+            expect(store.getState()).toEqual(expectedStore);
+            done();
+        });
+    });
+    /**
+     *  TODO Turn ON when FILTER TOGGLE Will BE REMOVED
+     */
+    /*
+    it('load certifed data', done => {
+        const store = storeCreator();
+
+        mockRest.addHandler('fetch', ({ data, options, baseUrl }) => {
+            expect(baseUrl).toEqual(
+                `/onboarding-api/v1.0/items?&itemStatus=${
+                    itemStatus.ACTIVE
+                }&versionStatus=${versionStatus.CERTIFIED}`
+            );
+            expect(data).toEqual(undefined);
+            expect(options).toEqual(undefined);
+            return {
+                results: [...vsps, ...vlms]
+            };
+        });
+
+        const expectedStore = cloneAndSet(
+            store.getState(),
+            'onboard.filter',
+            FilterFactory.build({ versionStatus: versionStatus.CERTIFIED })
+        );
+
+        const expectedFilteredItems = {
+            vspList: [
+                ...vsps.map(({ properties, ...other }) => ({
+                    ...other,
+                    ...properties
+                }))
+            ],
+            vlmList: [...vlms]
+        };
+        const expectedStoreWithFilteredLists = cloneAndSet(
+            expectedStore,
+            'filteredItems',
+            expectedFilteredItems
+        );
+        store.dispatch({
+            type: actionTypes.FILTER_DATA_CHANGED,
+            deltaData: { versionStatus: versionStatus.CERTIFIED }
+        });
+
+        return timeoutPromise.then(function() {
+            expect(store.getState()).toEqual(expectedStoreWithFilteredLists);
+            done();
+        });
+    });
+    */
+    it('onboarding tabs switching filter updates', done => {
+        const store = storeCreator();
+
+        mockRest.addHandler('fetch', ({ data, options, baseUrl }) => {
+            expect(baseUrl).toEqual(
+                `/onboarding-api/v1.0/items?&itemStatus=${
+                    itemStatus.ACTIVE
+                }&versionStatus=${versionStatus.CERTIFIED}`
+            );
+            expect(data).toEqual(undefined);
+            expect(options).toEqual(undefined);
+            return { results: [] };
+        });
+
+        expect(store.getState().onboard.filter.versionStatus).toEqual(
+            versionStatus.DRAFT
+        );
+
+        OnboardActionHelper.changeActiveTab(
+            store.dispatch,
+            tabsMapping.CATALOG
+        );
+
+        return timeoutPromise.then(() => {
+            expect(store.getState().onboard.filter.versionStatus).toEqual(
+                versionStatus.CERTIFIED
+            );
+            done();
+        });
+    });
+});
diff --git a/openecomp-ui/test/onboard/filter/filterView.test.js b/openecomp-ui/test/onboard/filter/filterView.test.js
new file mode 100644 (file)
index 0000000..536f02c
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * 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 { mount } from 'enzyme';
+import { Provider } from 'react-redux';
+import { storeCreator } from 'sdc-app/AppStore.js';
+import { ConnectedFilter } from 'sdc-app/onboarding//onboard//filter/Filter.jsx';
+
+describe('Filter component view Tests', () => {
+    it('simple jsx test', () => {
+        const store = storeCreator();
+        const wrapper = mount(
+            <Provider store={store}>
+                <ConnectedFilter />
+            </Provider>
+        );
+        const filter = wrapper.find('.catalog-filter');
+        expect(filter.hasClass('catalog-filter')).toBeTruthy();
+    });
+});
index 232c561..a75070b 100644 (file)
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-import {storeCreator} from 'sdc-app/AppStore.js';
-import {OnboardStoreFactory} from 'test-utils/factories/onboard/OnboardFactories.js';
+import { storeCreator } from 'sdc-app/AppStore.js';
+import { OnboardStoreFactory } from 'test-utils/factories/onboard/OnboardFactories.js';
 import OnboardActionHelper from 'sdc-app/onboarding/onboard/OnboardActionHelper.js';
 import OnboardingCatalogActionHelper from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogActionHelper.js';
-import {tabsMapping as onboardTabsMapping} from 'sdc-app/onboarding/onboard/OnboardConstants.js';
-import {tabsMapping as onboardCatalogTabsMapping} from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
+import { tabsMapping as onboardTabsMapping } from 'sdc-app/onboarding/onboard/OnboardConstants.js';
+import { tabsMapping as onboardCatalogTabsMapping } from 'sdc-app/onboarding/onboard/onboardingCatalog/OnboardingCatalogConstants.js';
+import { FilterFactory } from 'test-utils/factories/onboard/FilterFactories.js';
 
 describe('Onboard Module Tests', () => {
-       it('should return default state', () => {
-               const store = storeCreator();
-               const expectedStore = OnboardStoreFactory.build();
-               expect(store.getState().onboard).toEqual(expectedStore);
-       });
+    it('should return default state', () => {
+        const store = storeCreator();
+        const expectedStore = OnboardStoreFactory.build();
+        expect(store.getState().onboard).toEqual(expectedStore);
+    });
 
-       it('should change active tab to Catalog', () => {
-               const store = storeCreator();
-               const expectedStore = OnboardStoreFactory.build({activeTab: onboardTabsMapping.CATALOG});
-               OnboardActionHelper.changeActiveTab(store.dispatch, onboardTabsMapping.CATALOG);
-               expect(store.getState().onboard).toEqual(expectedStore);
-       });
+    it('should change active tab to Catalog', () => {
+        const store = storeCreator();
+        const expectedStore = OnboardStoreFactory.build({
+            activeTab: onboardTabsMapping.CATALOG,
+            filter: FilterFactory.build({ versionStatus: 'Certified' })
+        });
+        OnboardActionHelper.changeActiveTab(
+            store.dispatch,
+            onboardTabsMapping.CATALOG
+        );
+        expect(store.getState().onboard).toEqual(expectedStore);
+    });
 
-       it('should change searchValue', () => {
-               const store = storeCreator();
-               const expectedStore = OnboardStoreFactory.build({searchValue: 'hello'});
-               OnboardActionHelper.changeSearchValue(store.dispatch, 'hello');
-               expect(store.getState().onboard).toEqual(expectedStore);
-       });
+    it('should change searchValue', () => {
+        const store = storeCreator();
+        const expectedStore = OnboardStoreFactory.build({
+            searchValue: 'hello'
+        });
+        OnboardActionHelper.changeSearchValue(store.dispatch, 'hello');
+        expect(store.getState().onboard).toEqual(expectedStore);
+    });
 
-       it('should clear searchValue', () => {
-               const store = storeCreator();
-               const expectedStore = OnboardStoreFactory.build();
-               OnboardActionHelper.changeSearchValue(store.dispatch, 'hello');
-               OnboardActionHelper.clearSearchValue(store.dispatch);
-               expect(store.getState().onboard).toEqual(expectedStore);
-       });
-
-       it('should reset store', () => {
-               const store = storeCreator();
-               const expectedStore = OnboardStoreFactory.build();
-               OnboardActionHelper.changeSearchValue(store.dispatch, 'hello');
-               OnboardActionHelper.changeActiveTab(store.dispatch, onboardTabsMapping.CATALOG);
-               OnboardingCatalogActionHelper.changeActiveTab(store.dispatch, onboardCatalogTabsMapping.ACTIVE);
-               OnboardActionHelper.resetOnboardStore(store.dispatch, 'hello');
-               expect(store.getState().onboard).toEqual(expectedStore);
-       });
+    it('should clear searchValue', () => {
+        const store = storeCreator();
+        const expectedStore = OnboardStoreFactory.build();
+        OnboardActionHelper.changeSearchValue(store.dispatch, 'hello');
+        OnboardActionHelper.clearSearchValue(store.dispatch);
+        expect(store.getState().onboard).toEqual(expectedStore);
+    });
 
+    it('should reset store', () => {
+        const store = storeCreator();
+        const expectedStore = OnboardStoreFactory.build();
+        OnboardActionHelper.changeSearchValue(store.dispatch, 'hello');
+        OnboardActionHelper.changeActiveTab(
+            store.dispatch,
+            onboardTabsMapping.CATALOG
+        );
+        OnboardingCatalogActionHelper.changeActiveTab(
+            store.dispatch,
+            onboardCatalogTabsMapping.ACTIVE
+        );
+        OnboardActionHelper.resetOnboardStore(store.dispatch, 'hello');
+        expect(store.getState().onboard).toEqual(expectedStore);
+    });
 });
index e7b68d1..ac8d757 100644 (file)
@@ -9459,9 +9459,9 @@ scss-tokenizer@^0.2.3:
     js-base64 "^2.1.8"
     source-map "^0.4.2"
 
-sdc-ui@1.6.24:
-  version "1.6.24"
-  resolved "https://registry.yarnpkg.com/sdc-ui/-/sdc-ui-1.6.24.tgz#059b0fe6fdc36c962b65853a8012885aa38e78a7"
+sdc-ui@1.6.27:
+  version "1.6.27"
+  resolved "https://registry.yarnpkg.com/sdc-ui/-/sdc-ui-1.6.27.tgz#d4ade66b5792355fe5758e2b7231a11c1d4c137f"
   dependencies:
     "@angular/common" "~2.4.8"
     "@angular/core" "~2.4.8"