Healing process flow integration

Issue-ID: SDC-1360
Change-Id: I4d786b53b4357901d10e041c31145b7b1b065725
Signed-off-by: svishnev <shlomo-stanisla.vishnevetskiy@amdocs.com>
diff --git a/openecomp-ui/src/nfvo-components/notification/Notifications.js b/openecomp-ui/src/nfvo-components/notification/Notifications.js
new file mode 100644
index 0000000..046412a
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/notification/Notifications.js
@@ -0,0 +1,68 @@
+/*
+ * 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 { Portal, Notification } from 'sdc-ui/lib/react/';
+import { connect } from 'react-redux';
+import { removeNotification } from './NotificationsConstants.js';
+import { CSSTransition, TransitionGroup } from 'react-transition-group';
+
+export const mapStateToProps = ({ popupNotifications = [] }) => {
+    return {
+        notifications: popupNotifications
+    };
+};
+
+const mapActionToProps = dispatch => {
+    return {
+        onClick: item => {
+            dispatch(removeNotification(item));
+        }
+    };
+};
+
+class Notifications extends React.Component {
+    render() {
+        const { notifications, onClick } = this.props;
+
+        return (
+            <Portal>
+                <div className="onboarding-notifications-container position-top-right">
+                    <TransitionGroup>
+                        {notifications.map(item => (
+                            <CSSTransition
+                                in={true}
+                                timeout={500}
+                                unmountOnExit
+                                classNames="react-transition"
+                                key={`notification-transition-${item.id}`}>
+                                <Notification
+                                    key={item.id}
+                                    type={item.type}
+                                    title={item.title}
+                                    message={item.message}
+                                    onClick={() => onClick(item)}
+                                />
+                            </CSSTransition>
+                        ))}
+                    </TransitionGroup>
+                </div>
+            </Portal>
+        );
+    }
+}
+
+export default connect(mapStateToProps, mapActionToProps, null)(Notifications);
diff --git a/openecomp-ui/src/nfvo-components/notification/NotificationsConstants.js b/openecomp-ui/src/nfvo-components/notification/NotificationsConstants.js
new file mode 100644
index 0000000..329c557
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/notification/NotificationsConstants.js
@@ -0,0 +1,66 @@
+/*
+ * 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 UUID from 'uuid-js';
+
+export const actionTypes = {
+    ADD_NOTIFICATION: 'ADD_NOTIFICATION',
+    REMOVE_NOTIFICATION: 'REMOVE_NOTIFICATION'
+};
+
+export const notificationActions = {
+    showNotification: item => ({
+        type: actionTypes.ADD_NOTIFICATION,
+        payload: {
+            ...item,
+            id: UUID.create().toString()
+        }
+    }),
+
+    showSuccess: ({ title, message, timeout }) =>
+        notificationActions.showNotification({
+            title,
+            message,
+            timeout,
+            type: 'success'
+        }),
+    showInfo: ({ title, message, timeout }) =>
+        notificationActions.showNotification({
+            title,
+            message,
+            timeout,
+            type: 'info'
+        }),
+    showWarning: ({ title, message, timeout }) =>
+        notificationActions.showNotification({
+            title,
+            message,
+            timeout,
+            type: 'warning'
+        }),
+    showError: ({ title, message, timeout }) =>
+        notificationActions.showNotification({
+            title,
+            message,
+            timeout,
+            type: 'error'
+        }),
+    removeNotification: item => ({
+        type: actionTypes.REMOVE_NOTIFICATION,
+        payload: item
+    })
+};
+
+export const notificationTimeout = 4000;
diff --git a/openecomp-ui/src/nfvo-components/notification/NotificationsMiddleware.js b/openecomp-ui/src/nfvo-components/notification/NotificationsMiddleware.js
new file mode 100644
index 0000000..f32f20b
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/notification/NotificationsMiddleware.js
@@ -0,0 +1,33 @@
+/*
+ * 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,
+    notificationActions,
+    notificationTimeout
+} from './NotificationsConstants.js';
+
+const notifications = store => next => action => {
+    if (action.type === actionTypes.ADD_NOTIFICATION) {
+        const { timeout, ...data } = action.payload;
+        const interval = timeout || notificationTimeout;
+        setTimeout(() => {
+            store.dispatch(notificationActions.removeNotification(data));
+        }, interval);
+    }
+    return next(action);
+};
+
+export default notifications;
diff --git a/openecomp-ui/src/nfvo-components/notification/NotificationsReducer.js b/openecomp-ui/src/nfvo-components/notification/NotificationsReducer.js
new file mode 100644
index 0000000..9b97381
--- /dev/null
+++ b/openecomp-ui/src/nfvo-components/notification/NotificationsReducer.js
@@ -0,0 +1,28 @@
+/*
+ * 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 './NotificationsConstants';
+
+export default (state = [], action) => {
+    switch (action.type) {
+        case actionTypes.ADD_NOTIFICATION:
+            return [...state, action.payload];
+
+        case actionTypes.REMOVE_NOTIFICATION:
+            return state.filter(item => item.id !== action.payload.id);
+        default:
+            return state;
+    }
+};
diff --git a/openecomp-ui/src/nfvo-utils/i18n/en.json b/openecomp-ui/src/nfvo-utils/i18n/en.json
index 10ddb42..d02904d 100644
--- a/openecomp-ui/src/nfvo-utils/i18n/en.json
+++ b/openecomp-ui/src/nfvo-utils/i18n/en.json
@@ -364,7 +364,8 @@
   "Contributor": "Contributor",
   "Active Items": "Active Items",
   "Archived Items": "Archived Items",
-
+  "This is the current version of the VSP, as a result of healing": "This is the current version of the VSP, as a result of healing",
+  
   "VendorSoftwareProduct": "VSP",
   "VendorSoftwareProduct/category": "Category",
   "VendorSoftwareProduct/description": "Description",
diff --git a/openecomp-ui/src/sdc-app/AppStore.js b/openecomp-ui/src/sdc-app/AppStore.js
index 5cab6ae..db47650 100644
--- a/openecomp-ui/src/sdc-app/AppStore.js
+++ b/openecomp-ui/src/sdc-app/AppStore.js
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2016-2017 European Support Limited
+ * 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.
@@ -17,6 +17,7 @@
 import { createStore, applyMiddleware, compose } from 'redux';
 import Reducers from './Reducers.js';
 import filterUpdater from 'sdc-app/onboarding/onboard/filter/FilterMiddleware.js';
+import notifications from 'nfvo-components/notification/NotificationsMiddleware.js';
 
 const thunk = store => next => action =>
     typeof action === 'function'
@@ -29,7 +30,7 @@
     createStore(
         Reducers,
         initialState,
-        composeEnhancers(applyMiddleware(thunk, filterUpdater))
+        composeEnhancers(applyMiddleware(thunk, filterUpdater, notifications))
     );
 
 const store = storeCreator();
diff --git a/openecomp-ui/src/sdc-app/Application.jsx b/openecomp-ui/src/sdc-app/Application.jsx
index abebb6d..f96bd73 100644
--- a/openecomp-ui/src/sdc-app/Application.jsx
+++ b/openecomp-ui/src/sdc-app/Application.jsx
@@ -1,5 +1,5 @@
 /*!
- * Copyright © 2016-2017 European Support Limited
+ * 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.
@@ -17,6 +17,7 @@
 import PropTypes from 'prop-types';
 import { Provider } from 'react-redux';
 import GlobalModal from 'nfvo-components/modal/GlobalModal.js';
+import Notifications from 'nfvo-components/notification/Notifications.js';
 import Loader from 'nfvo-components/loader/Loader.jsx';
 import WebSocketUtil from 'nfvo-utils/WebSocketUtil.js';
 import UserNotificationsActionHelper from 'sdc-app/onboarding/userNotifications/UserNotificationsActionHelper.js';
@@ -44,6 +45,7 @@
             <Provider store={store}>
                 <div>
                     <GlobalModal />
+                    <Notifications />
                     {this.props.children}
                     <Loader />
                 </div>
diff --git a/openecomp-ui/src/sdc-app/Reducers.js b/openecomp-ui/src/sdc-app/Reducers.js
index 9f42423..684c20c 100644
--- a/openecomp-ui/src/sdc-app/Reducers.js
+++ b/openecomp-ui/src/sdc-app/Reducers.js
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2016-2017 European Support Limited
+ * 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.
@@ -20,7 +20,7 @@
 import loaderReducer from 'nfvo-components/loader/LoaderReducer.js';
 import globalModalReducer from 'nfvo-components/modal/GlobalModalReducer.js';
 import notificationsReducer from 'sdc-app/onboarding/userNotifications/NotificationsReducer.js';
-
+import { default as popupNotifications } from 'nfvo-components/notification/NotificationsReducer.js';
 export default combineReducers({
     // on-boarding reducers
     ...onBoardingReducersMap,
@@ -29,5 +29,6 @@
     ...flowsReducersMap,
     modal: globalModalReducer,
     loader: loaderReducer,
-    notifications: notificationsReducer
+    notifications: notificationsReducer,
+    popupNotifications
 });
diff --git a/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js b/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
index b8ce714..b9ffdc3 100644
--- a/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
+++ b/openecomp-ui/src/sdc-app/onboarding/OnboardingActionHelper.js
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2016-2017 European Support Limited
+ * 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.
@@ -47,6 +47,8 @@
 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';
+import { notificationActions } from 'nfvo-components/notification/NotificationsConstants.js';
+import i18n from 'nfvo-utils/i18n/i18n.js';
 
 function setCurrentScreen(dispatch, screen, props = {}) {
     dispatch({
@@ -208,37 +210,82 @@
             status
         });
     },
+    async getUpdatedSoftwareProduct(dispatch, { softwareProductId, version }) {
+        const response = await SoftwareProductActionHelper.fetchSoftwareProduct(
+            dispatch,
+            {
+                softwareProductId,
+                version
+            }
+        );
+        let newResponse = false;
+        let newVersion = false;
+        // checking if there was healing and a new version should be open
+        if (response[0].version !== version.id) {
+            newResponse = await SoftwareProductActionHelper.fetchSoftwareProduct(
+                dispatch,
+                {
+                    softwareProductId,
+                    version: { ...version, id: response[0].version }
+                }
+            );
+            newVersion = await ItemsHelper.fetchVersion({
+                itemId: softwareProductId,
+                versionId: response[0].version
+            });
 
-    navigateToSoftwareProductLandingPage(
+            dispatch(
+                notificationActions.showInfo({
+                    message: i18n(
+                        'This is the current version of the VSP, as a result of healing'
+                    )
+                })
+            );
+        }
+        return Promise.resolve(
+            newResponse
+                ? { softwareProduct: newResponse[0], newVersion }
+                : { softwareProduct: response[0], newVersion: version }
+        );
+    },
+    async navigateToSoftwareProductLandingPage(
         dispatch,
         { softwareProductId, version, status }
     ) {
         SoftwareProductComponentsActionHelper.clearComponentsStore(dispatch);
+        /**
+         * TODO remove when Filter toggle will be removed
+         */
         LicenseModelActionHelper.fetchFinalizedLicenseModels(dispatch);
-        SoftwareProductActionHelper.fetchSoftwareProduct(dispatch, {
+
+        const {
+            softwareProduct,
+            newVersion
+        } = await this.getUpdatedSoftwareProduct(dispatch, {
             softwareProductId,
             version
-        }).then(response => {
-            let { vendorId: licenseModelId, licensingVersion } = response[0];
-            SoftwareProductActionHelper.loadSoftwareProductDetailsData(
+        });
+
+        let { vendorId: licenseModelId, licensingVersion } = softwareProduct;
+        SoftwareProductActionHelper.loadSoftwareProductDetailsData(dispatch, {
+            licenseModelId,
+            licensingVersion
+        });
+        SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(
+            dispatch,
+            { softwareProductId, version: newVersion }
+        );
+        if (softwareProduct.onboardingOrigin === onboardingOriginTypes.ZIP) {
+            SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(
                 dispatch,
-                { licenseModelId, licensingVersion }
+                { softwareProductId, version: newVersion }
             );
-            SoftwareProductComponentsActionHelper.fetchSoftwareProductComponents(
-                dispatch,
-                { softwareProductId, version: version }
-            );
-            if (response[0].onboardingOrigin === onboardingOriginTypes.ZIP) {
-                SoftwareProductActionHelper.loadSoftwareProductHeatCandidate(
-                    dispatch,
-                    { softwareProductId, version: version }
-                );
-            }
-            setCurrentScreen(
-                dispatch,
-                enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE,
-                { softwareProductId, licenseModelId, version, status }
-            );
+        }
+        setCurrentScreen(dispatch, enums.SCREEN.SOFTWARE_PRODUCT_LANDING_PAGE, {
+            softwareProductId,
+            licenseModelId,
+            version: newVersion,
+            status
         });
     },
 
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js
index db3cc04..d3d7b96 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/SoftwareProduct.js
@@ -127,7 +127,8 @@
     screen,
     componentId,
     componentsList,
-    mapOfExpandedIds
+    mapOfExpandedIds,
+    isCertified
 }) => {
     const {
         softwareProductEditor: { data: currentSoftwareProduct = {} }
@@ -235,7 +236,7 @@
     return {
         activeItemId,
         groups,
-        disabled: !!candidateOnboardingOrigin
+        disabled: !!candidateOnboardingOrigin && !isCertified
     };
 };
 
@@ -268,7 +269,8 @@
         userInfo,
         usersList,
         isManual: onboardingMethod === onboardingMethodType.MANUAL,
-        candidateInProcess: !!candidateOnboardingOrigin
+        candidateInProcess:
+            !!candidateOnboardingOrigin && !itemPermission.isCertified
     };
 };
 
@@ -360,7 +362,8 @@
             screen,
             componentId,
             componentsList,
-            mapOfExpandedIds
+            mapOfExpandedIds,
+            isCertified: itemPermission.isCertified
         }),
         meta
     };
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js
index 4d5887b..9b0f681 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/attachments/SoftwareProductAttachments.js
@@ -36,7 +36,8 @@
                 heatSetupCache,
                 heatValidation: { errorList }
             }
-        }
+        },
+        currentScreen: { itemPermission: { isCertified } }
     } = state;
 
     let { unassigned = [], modules = [] } = heatSetup;
@@ -61,7 +62,8 @@
         version,
         onboardingOrigin,
         activeTab,
-        candidateInProcess: !!currentSoftwareProduct.candidateOnboardingOrigin
+        candidateInProcess:
+            !!currentSoftwareProduct.candidateOnboardingOrigin && !isCertified
     };
 };
 
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js
index f5f3b7e..52a6980 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPage.js
@@ -25,7 +25,8 @@
 
 export const mapStateToProps = ({
     softwareProduct,
-    licenseModel: { licenseAgreement }
+    licenseModel: { licenseAgreement },
+    currentScreen: { itemPermission: { isCertified } }
 }) => {
     let {
         softwareProductEditor: { data: currentSoftwareProduct = {} },
@@ -67,6 +68,7 @@
             licenseAgreementName,
             fullCategoryDisplayName
         },
+        isCertified,
         componentsList,
         isManual:
             currentSoftwareProduct.onboardingMethod === onboardingMethod.MANUAL
diff --git a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx
index 00f0c2a..dcc9645 100644
--- a/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx
+++ b/openecomp-ui/src/sdc-app/onboarding/softwareProduct/landingPage/SoftwareProductLandingPageView.jsx
@@ -65,8 +65,12 @@
         onAddComponent: PropTypes.func
     };
     componentDidMount() {
-        const { onCandidateInProcess, currentSoftwareProduct } = this.props;
-        if (currentSoftwareProduct.candidateOnboardingOrigin) {
+        const {
+            onCandidateInProcess,
+            currentSoftwareProduct,
+            isCertified
+        } = this.props;
+        if (currentSoftwareProduct.candidateOnboardingOrigin && !isCertified) {
             onCandidateInProcess(currentSoftwareProduct.id);
         }
     }