Implementing user feed back 85/29685/1
authorarul.nambi <arul.nambi@amdocs.com>
Tue, 30 Jan 2018 17:34:34 +0000 (12:34 -0500)
committerarul.nambi <arul.nambi@amdocs.com>
Tue, 30 Jan 2018 19:00:30 +0000 (14:00 -0500)
Change-Id: I66196a4a5a319bb9c78c503244c0e78824ac855a
Signed-off-by: arul.nambi <arul.nambi@amdocs.com>
Issue-ID: AAI-696

14 files changed:
package.json
resources/scss/common/_layout.scss
src/app/tierSupport/TierSupport.jsx
src/app/tierSupport/TierSupportActions.js
src/app/tierSupport/TierSupportConstants.js
src/app/tierSupport/TierSupportReducer.js
src/app/vnfSearch/VnfSearchActions.js
src/app/vnfSearch/VnfSearchConstants.js
src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx
src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx
src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx
src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx
src/app/vnfSearch/VnfSearchReducer.js
src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx

index 325c418..ddbc889 100644 (file)
@@ -41,6 +41,7 @@
     "react-redux": "^4.4.1",
     "react-router-dom": "^4.1.1",
     "react-select": "^1.0.0-beta13",
+    "react-spinners": "^0.2.5",
     "react-split-pane": "^0.1.51",
     "redux": "^3.3.1",
     "redux-form": "^6.2.1",
index 1c3bf66..07b5b4c 100644 (file)
 
 .view-container {
 }
+
+.hideContainer {
+       visibility: hidden
+}
+
+.showContainer {
+}
+
+.spinner {
+       position: fixed;
+       z-index: 999;
+       height: 2em;
+       width: 2em;
+       margin: auto;
+       top: 0;
+       left: 0;
+       bottom: 0;
+       right: 0;
+}
\ No newline at end of file
index 315b6a0..943943f 100644 (file)
@@ -24,6 +24,8 @@
 import React, {Component} from 'react';
 import {connect} from 'react-redux';
 import SplitPane from 'react-split-pane';
+import { ClipLoader } from 'react-spinners';
+import {COLOR_BLUE} from 'utils/GlobalConstants.js';
 
 import {setSecondaryTitle} from 'app/MainScreenWrapperActionHelper.js';
 import ForceDirectedGraph from 'generic-components/graph/ForceDirectedGraph.jsx';
@@ -69,7 +71,8 @@ let mapStateToProps = (
         graphNodeSelectedMenu = TSUI_GRAPH_MENU_NODE_DETAILS,
         feedbackMsgText = '',
         feedbackMsgSeverity = '',
-        nodeData = {}
+        nodeData = {},
+        enableBusyFeedback = false
       } = tierSupportReducer;
 
   let {
@@ -85,7 +88,8 @@ let mapStateToProps = (
     selectedSuggestion,
     feedbackMsgText,
     feedbackMsgSeverity,
-    nodeData
+    nodeData,
+    enableBusyFeedback
   };
 };
 
@@ -123,7 +127,8 @@ class TierSupport extends Component {
     graphNodeSelectedMenu: React.PropTypes.string,
     feedbackMsgText: React.PropTypes.string,
     feedbackMsgSeverity: React.PropTypes.string,
-    nodeData: React.PropTypes.object
+    nodeData: React.PropTypes.object,
+    enableBusyFeedback: React.PropTypes.bool
   };
 
   componentWillReceiveProps(nextProps) {
@@ -169,10 +174,14 @@ class TierSupport extends Component {
             windowWidth,
             windowHeight,
             onSplitPaneResize,
-            onNodeMenuSelect
+            onNodeMenuSelect,
+            enableBusyFeedback
           } = this.props;
 
-
+    let componentVisibitliyClassName = 'showContainer';
+    if(enableBusyFeedback){
+      componentVisibitliyClassName = 'hideContainer';
+    }
     let availableOverlay;
     let overlayComponent;
     // Currently only ONE overlay can be added to each view.
@@ -200,35 +209,40 @@ class TierSupport extends Component {
     let currentSelectedMenu = this.getCurrentSelectedMenu(overlayComponent);
     return (
       <div className='tier-support-ui'>
-        <SplitPane
-          split='vertical'
-          enableResizing='true'
-          onDragFinished={ () => {
-            onSplitPaneResize(false);
-          } }
-          defaultSize={TSUI_NODE_DETAILS_INITIAL_WIDTH}
-          minSize={TSUI_NODE_DETAILS_MIN_WIDTH}
-          maxSize={-200}
-          primary='second'>
-          <div>
-            <ForceDirectedGraph
-              viewWidth={windowWidth}
-              viewHeight={windowHeight}
-              graphData={forceDirectedGraphRawData}
-              nodeSelectedCallback={(nodeData) => {
-                onNodeSelected(nodeData);
-              }}
-              nodeButtonSelectedCallback={(selectedMenuId) => {
-                onNodeMenuSelect(selectedMenuId);
-              }}
-              dataOverlayButtons={dataOverlayButtons}
-              currentlySelectedNodeView={currentNodeButton}/>
+          <div className='spinner'>
+              <ClipLoader color={COLOR_BLUE} loading={enableBusyFeedback} />
+            </div>
+          <div className={componentVisibitliyClassName}>
+            <SplitPane
+              split='vertical'
+              enableResizing='true'
+              onDragFinished={ () => {
+                onSplitPaneResize(false);
+              } }
+              defaultSize={TSUI_NODE_DETAILS_INITIAL_WIDTH}
+              minSize={TSUI_NODE_DETAILS_MIN_WIDTH}
+              maxSize={-200}
+              primary='second'>
+              <div>
+                <ForceDirectedGraph
+                  viewWidth={windowWidth}
+                  viewHeight={windowHeight}
+                  graphData={forceDirectedGraphRawData}
+                  nodeSelectedCallback={(nodeData) => {
+                    onNodeSelected(nodeData);
+                  }}
+                  nodeButtonSelectedCallback={(selectedMenuId) => {
+                    onNodeMenuSelect(selectedMenuId);
+                  }}
+                  dataOverlayButtons={dataOverlayButtons}
+                  currentlySelectedNodeView={currentNodeButton}/>
 
+              </div>
+              <div>
+                {currentSelectedMenu}
+              </div>
+            </SplitPane>
           </div>
-          <div>
-            {currentSelectedMenu}
-          </div>
-        </SplitPane>
       </div>
     );
   }
index ead321e..fc4bcad 100644 (file)
@@ -120,6 +120,18 @@ export function clearVIData() {
   };
 }
 
+function setBusyFeedback(){
+  return {
+    type: tierSupportActionTypes.TIER_SUPPORT_ACTIVATE_BUSY_FEEDBACK
+  };
+}
+
+function disableBusyFeedback(){
+  return {
+    type: tierSupportActionTypes.TIER_SUPPORT_DISABLE_BUSY_FEEDBACK
+  };
+}
+
 export function fetchSelectedNodeElement(fetchRequestCallback) {
   return dispatch => {
     return fetchRequestCallback().then(
@@ -140,8 +152,13 @@ export function fetchSelectedNodeElement(fetchRequestCallback) {
           dispatch(noNodeDetailsFoundEvent(NO_RESULTS_FOUND));
         }
       }
+    ).then(
+      () => {
+        dispatch(disableBusyFeedback());
+      }
     ).catch(
       (errorCode) => {
+        dispatch(disableBusyFeedback());
         if (errorCode.message >= STATUS_CODE_5XX_SERVER_ERROR) {
           dispatch(getInvalidSelectedNodeSearchEvent(ERROR_RETRIEVING_DATA));
         } else {
@@ -169,6 +186,7 @@ export function querySelectedNodeElement(
   }
 
   return dispatch => {
+    dispatch(setBusyFeedback());
     dispatch(fetchSelectedNodeElement(selectedNodeFetchRequest));
   };
 }
index d20325f..d66816e 100644 (file)
@@ -32,7 +32,9 @@ export const tierSupportActionTypes = keyMirror({
   TS_GRAPH_NODE_SELECTED: null,
   TS_GRAPH_NODE_MENU_SELECTED: null,
   SPLIT_PANE_RESIZE: null,
-  TIER_SUPPORT_CLEAR_DATA: null
+  TIER_SUPPORT_CLEAR_DATA: null,
+  TIER_SUPPORT_ACTIVATE_BUSY_FEEDBACK: null,
+  TIER_SUPPORT_DISABLE_BUSY_FEEDBACK: null
 });
 
 export const TSUI_NODE_DETAILS_INITIAL_WIDTH = 300;
index 1560427..c9a4faf 100644 (file)
@@ -89,6 +89,16 @@ export default combineReducers({
           ...state,
           nodeData: action.data
         };
+      case tierSupportActionTypes.TIER_SUPPORT_ACTIVATE_BUSY_FEEDBACK:
+        return {
+          ...state,
+          enableBusyFeedback: true
+        };
+      case tierSupportActionTypes.TIER_SUPPORT_DISABLE_BUSY_FEEDBACK:
+        return {
+          ...state,
+          enableBusyFeedback: false
+        };  
       case globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT:
         let emptyNodesAndLinksWarningEvent = ForceDirectedGraph.generateNewProps([], [], {});
         return {
index 0167962..156f541 100644 (file)
@@ -205,8 +205,21 @@ function getVnfVisualizationsResultsEvent(results) {
   };
 }
 
+function setBusyFeedback(){
+  return {
+    type: vnfActionTypes.VNF_ACTIVATE_BUSY_FEEDBACK
+  };
+}
+
+function disableBusyFeedback(){
+  return {
+    type: vnfActionTypes.VNF_DISABLE_BUSY_FEEDBACK
+  };
+}
+
 export function processVnfVisualizationsOnFilterChange(filterValueMap) {
   return dispatch => {
+    dispatch(setBusyFeedback());
     return fetch(VNF_FILTER_AGGREGATION_URL, {
       method: POST,
       headers: POST_HEADER,
@@ -222,8 +235,13 @@ export function processVnfVisualizationsOnFilterChange(filterValueMap) {
         }
         dispatch(getVnfVisualizationsResultsEvent(responseJson));
       }
+    ).then(
+      () => {
+        dispatch(disableBusyFeedback());
+      }
     ).catch(
       () => {
+        dispatch(disableBusyFeedback());
         dispatch(getInvalidQueryEvent());
       }
     );
index 97d7159..200d01f 100644 (file)
@@ -30,7 +30,9 @@ export const vnfActionTypes = keyMirror({
   VNF_NETWORK_ERROR: null,
   VNF_SEARCH_RESULTS_RECEIVED: null,
   VNF_SEARCH_FILTERS_RECEIVED: null,
-  VNF_FILTER_PANEL_TOGGLED: null
+  VNF_FILTER_PANEL_TOGGLED: null,
+  VNF_ACTIVATE_BUSY_FEEDBACK: null,
+  VNF_DISABLE_BUSY_FEEDBACK: null
 });
 
 export const CHART_PROV_STATUS = {
index ca6f269..806ab3a 100644 (file)
@@ -36,27 +36,35 @@ import i18n from 'utils/i18n/i18n';
 
 import {CHART_NF_ROLE} from 'app/vnfSearch/VnfSearchConstants.js';
 import {COLOR_BLUE} from 'utils/GlobalConstants.js';
+import { ClipLoader } from 'react-spinners';
 
 let mapStateToProps = ({vnfSearch}) => {
   let {
-        processedNfRoleCountChartData = CHART_NF_ROLE.emptyData
+        processedNfRoleCountChartData = CHART_NF_ROLE.emptyData,
+        enableBusyFeedback = false
       } = vnfSearch;
 
   return {
-    processedNfRoleCountChartData
+    processedNfRoleCountChartData,
+    enableBusyFeedback
   };
 };
 
 class VnfSearchNfRoleVisualization extends Component {
   static propTypes = {
-    processedNfRoleCountChartData: React.PropTypes.object
+    processedNfRoleCountChartData: React.PropTypes.object,
+    enableBusyFeedback: React.PropTypes.bool
   };
 
   render() {
     let {
-          processedNfRoleCountChartData
+          processedNfRoleCountChartData,
+          enableBusyFeedback
         } = this.props;
-
+    let componentVisibitliyClassName = 'showContainer';
+    if(enableBusyFeedback){
+      componentVisibitliyClassName = 'hideContainer';
+    }
     let visualizationClass = 'visualizations';
 
     if (processedNfRoleCountChartData.values ===
@@ -74,16 +82,21 @@ class VnfSearchNfRoleVisualization extends Component {
         <div className='visualization-charts'>
           <div>
             <h3>{i18n(CHART_NF_ROLE.title)}</h3>
-            <ResponsiveContainer width='100%' height={300}>
-              <BarChart data={processedNfRoleCountChartData.values}>
-                <XAxis dataKey={xAxisAttrName}/>
-                <YAxis/>
-                <CartesianGrid strokeDasharray='3 3'/>
-                <Tooltip/>
-                <Bar name={i18n(CHART_NF_ROLE.yAxisLabel)}
-                     dataKey={yAxisAttrName} fill={COLOR_BLUE}/>
-              </BarChart>
-            </ResponsiveContainer>
+            <div className='spinner'>
+              <ClipLoader color={COLOR_BLUE} loading={enableBusyFeedback} />
+            </div>
+            <div className={componentVisibitliyClassName}>
+              <ResponsiveContainer width='100%' height={300}>
+                <BarChart data={processedNfRoleCountChartData.values}>
+                  <XAxis dataKey={xAxisAttrName}/>
+                  <YAxis/>
+                  <CartesianGrid strokeDasharray='3 3'/>
+                  <Tooltip/>
+                  <Bar name={i18n(CHART_NF_ROLE.yAxisLabel)}
+                       dataKey={yAxisAttrName} fill={COLOR_BLUE}/>
+                </BarChart>
+              </ResponsiveContainer>
+            </div>
           </div>
         </div>
       </div>
index 30c6cdc..3f4acf0 100644 (file)
@@ -36,27 +36,35 @@ import i18n from 'utils/i18n/i18n';
 
 import {CHART_NF_TYPE} from 'app/vnfSearch/VnfSearchConstants.js';
 import {COLOR_BLUE} from 'utils/GlobalConstants.js';
+import { ClipLoader } from 'react-spinners';
 
 let mapStateToProps = ({vnfSearch}) => {
   let {
-        processedNfTypeCountChartData = CHART_NF_TYPE.emptyData
+        processedNfTypeCountChartData = CHART_NF_TYPE.emptyData,
+        enableBusyFeedback = false
       } = vnfSearch;
 
   return {
-    processedNfTypeCountChartData
+    processedNfTypeCountChartData,
+    enableBusyFeedback
   };
 };
 
 class VnfSearchNfTypeVisualization extends Component {
   static propTypes = {
-    processedNfTypeCountChartData: React.PropTypes.object
+    processedNfTypeCountChartData: React.PropTypes.object,
+    enableBusyFeedback: React.PropTypes.bool
   };
 
   render() {
     let {
-          processedNfTypeCountChartData
+          processedNfTypeCountChartData,
+          enableBusyFeedback
         } = this.props;
-
+    let componentVisibitliyClassName = 'showContainer';
+    if(enableBusyFeedback){
+      componentVisibitliyClassName = 'hideContainer';
+    }
     let visualizationClass = 'visualizations';
     if (processedNfTypeCountChartData.values ===
       null ||
@@ -72,16 +80,21 @@ class VnfSearchNfTypeVisualization extends Component {
         <div className='visualization-charts'>
           <div >
             <h3>{i18n(CHART_NF_TYPE.title)}</h3>
-            <ResponsiveContainer width='100%' height={300}>
-              <BarChart data={processedNfTypeCountChartData.values}>
-                <XAxis dataKey={xAxisAttrName}/>
-                <YAxis   />
-                <CartesianGrid strokeDasharray='3 3'/>
-                <Tooltip/>
-                <Bar name={i18n(CHART_NF_TYPE.yAxisLabel)}
-                     dataKey={yAxisAttrName} fill={COLOR_BLUE}/>
-              </BarChart>
-            </ResponsiveContainer>
+            <div className='spinner'>
+              <ClipLoader color={COLOR_BLUE} loading={enableBusyFeedback} />
+            </div>
+            <div className={componentVisibitliyClassName}>
+              <ResponsiveContainer width='100%' height={300}>
+                <BarChart data={processedNfTypeCountChartData.values}>
+                  <XAxis dataKey={xAxisAttrName}/>
+                  <YAxis   />
+                  <CartesianGrid strokeDasharray='3 3'/>
+                  <Tooltip/>
+                  <Bar name={i18n(CHART_NF_TYPE.yAxisLabel)}
+                       dataKey={yAxisAttrName} fill={COLOR_BLUE}/>
+                </BarChart>
+              </ResponsiveContainer>
+            </div>
           </div>
         </div>
       </div>
index 1855db7..7cc29d8 100644 (file)
@@ -36,25 +36,35 @@ import i18n from 'utils/i18n/i18n';
 
 import {CHART_ORCH_STATUS} from 'app/vnfSearch/VnfSearchConstants.js';
 import {COLOR_BLUE} from 'utils/GlobalConstants.js';
-
+import { ClipLoader } from 'react-spinners';
 
 let mapStateToProps = ({vnfSearch}) => {
   let {
-        processedOrchStatusCountChartData = CHART_ORCH_STATUS.emptyData
+        processedOrchStatusCountChartData = CHART_ORCH_STATUS.emptyData,
+        enableBusyFeedback = false
       } = vnfSearch;
 
   return {
-    processedOrchStatusCountChartData
+    processedOrchStatusCountChartData,
+    enableBusyFeedback
   };
 };
 
 class VnfSearchOrchStatusVisualizations extends Component {
+  static propTypes = {
+    processedOrchStatusCountChartData: React.PropTypes.object,
+    enableBusyFeedback: React.PropTypes.bool
+  };
 
   render() {
     let {
-                                               processedOrchStatusCountChartData
+                                               processedOrchStatusCountChartData,
+            enableBusyFeedback
                                } = this.props;
-
+    let componentVisibitliyClassName = 'showContainer';
+    if(enableBusyFeedback){
+      componentVisibitliyClassName = 'hideContainer';
+    }
     let visualizationClass = 'visualizations';
     if (processedOrchStatusCountChartData.values ===
       null ||
@@ -70,16 +80,21 @@ class VnfSearchOrchStatusVisualizations extends Component {
         <div className='visualization-charts'>
           <div >
             <h3>{i18n(CHART_ORCH_STATUS.title)}</h3>
-            <ResponsiveContainer width='100%' height={300}>
-              <BarChart data={processedOrchStatusCountChartData.values}>
-                <XAxis dataKey={xAxisAttrName}/>
-                <YAxis   />
-                <CartesianGrid strokeDasharray='3 3'/>
-                <Tooltip/>
-                <Bar name={i18n(CHART_ORCH_STATUS.yAxisLabel)}
-                     dataKey={yAxisAttrName} fill={COLOR_BLUE}/>
-              </BarChart>
-            </ResponsiveContainer>
+            <div className='spinner'>
+              <ClipLoader color={COLOR_BLUE} loading={enableBusyFeedback} />
+            </div>
+            <div className={componentVisibitliyClassName}>
+              <ResponsiveContainer width='100%' height={300}>
+                <BarChart data={processedOrchStatusCountChartData.values}>
+                  <XAxis dataKey={xAxisAttrName}/>
+                  <YAxis   />
+                  <CartesianGrid strokeDasharray='3 3'/>
+                  <Tooltip/>
+                  <Bar name={i18n(CHART_ORCH_STATUS.yAxisLabel)}
+                       dataKey={yAxisAttrName} fill={COLOR_BLUE}/>
+                </BarChart>
+              </ResponsiveContainer>
+            </div>
           </div>
         </div>
       </div>
index cdf6872..7ef6e9e 100644 (file)
@@ -36,27 +36,36 @@ import i18n from 'utils/i18n/i18n';
 
 import {CHART_PROV_STATUS} from 'app/vnfSearch/VnfSearchConstants.js';
 import {COLOR_BLUE} from 'utils/GlobalConstants.js';
+import { ClipLoader } from 'react-spinners';
 
 let mapStateToProps = ({vnfSearch}) => {
   let {
-        processedProvStatusCountChartData = CHART_PROV_STATUS.emptyData
+        processedProvStatusCountChartData = CHART_PROV_STATUS.emptyData,
+        enableBusyFeedback = false
       } = vnfSearch;
 
   return {
-    processedProvStatusCountChartData
+    processedProvStatusCountChartData,
+    enableBusyFeedback
   };
 };
 
 class VnfSearchProvStatusVisualization extends Component {
   static propTypes = {
-    processedProvStatusCountChartData: React.PropTypes.object
+    processedProvStatusCountChartData: React.PropTypes.object,
+    enableBusyFeedback: React.PropTypes.bool
   };
 
   render() {
     let {
-                                               processedProvStatusCountChartData
+                                               processedProvStatusCountChartData,
+            enableBusyFeedback
                                } = this.props;
 
+    let componentVisibitliyClassName = 'showContainer';
+    if(enableBusyFeedback){
+      componentVisibitliyClassName = 'hideContainer';
+    }
     let visualizationClass = 'visualizations';
     if (processedProvStatusCountChartData.values ===
       null ||
@@ -72,17 +81,22 @@ class VnfSearchProvStatusVisualization extends Component {
         <div className='visualization-charts'>
           <div className='visualization-side-by-side-70'>
             <h3>{i18n(CHART_PROV_STATUS.title)}</h3>
-            <ResponsiveContainer width='100%' height={300}>
-              <BarChart
-                data={processedProvStatusCountChartData.values}>
-                <XAxis dataKey={xAxisAttrName}/>
-                <YAxis  />
-                <CartesianGrid strokeDasharray='3 3'/>
-                <Tooltip/>
-                <Bar name={i18n(CHART_PROV_STATUS.xAxisLabel)}
-                     dataKey={yAxisAttrName} fill={COLOR_BLUE}/>
-              </BarChart>
-            </ResponsiveContainer>
+            <div className='spinner'>
+              <ClipLoader color={COLOR_BLUE} loading={enableBusyFeedback} />
+            </div>
+            <div className={componentVisibitliyClassName}>
+              <ResponsiveContainer width='100%' height={345} >
+                  <BarChart
+                    data={processedProvStatusCountChartData.values}>
+                    <XAxis dataKey={xAxisAttrName}/>
+                    <YAxis  />
+                    <CartesianGrid strokeDasharray='3 3'/>
+                    <Tooltip/>
+                    <Bar name={i18n(CHART_PROV_STATUS.xAxisLabel)}
+                         dataKey={yAxisAttrName} fill={COLOR_BLUE}/>
+                  </BarChart>
+                </ResponsiveContainer>
+              </div>
           </div>
         </div>
       </div>
@@ -90,4 +104,4 @@ class VnfSearchProvStatusVisualization extends Component {
   }
 
 }
-export default connect(mapStateToProps)(VnfSearchProvStatusVisualization);
+export default connect(mapStateToProps)(VnfSearchProvStatusVisualization);
\ No newline at end of file
index 1394f97..afd822c 100644 (file)
@@ -105,6 +105,16 @@ export default (state = {}, action) => {
         vnfFilterValues: data.nonConvertedValues  // launching DI view via menu button requires this
                                                   // to be set so visualizations and table will populate themselves
       };
+    case vnfActionTypes.VNF_ACTIVATE_BUSY_FEEDBACK:
+      return {
+        ...state,
+        enableBusyFeedback: true
+      };
+    case vnfActionTypes.VNF_DISABLE_BUSY_FEEDBACK:
+      return {
+        ...state,
+        enableBusyFeedback: false
+      }; 
     case filterBarActionTypes.CLEAR_FILTERS:
       return {
         ...state,
index a2abd7c..553de42 100644 (file)
@@ -26,14 +26,18 @@ import {connect} from 'react-redux';
 import i18n from 'utils/i18n/i18n';
 
 import {TOTAL_VNF_COUNT} from 'app/vnfSearch/VnfSearchConstants.js';
+import {COLOR_BLUE} from 'utils/GlobalConstants.js';
+import { ClipLoader } from 'react-spinners';
 
 let mapStateToProps = ({vnfSearch}) => {
   let {
-        count = TOTAL_VNF_COUNT.emptyValue
+        count = TOTAL_VNF_COUNT.emptyValue,
+        enableBusyFeedback = false
       } = vnfSearch;
 
   return {
-    count
+    count,
+    enableBusyFeedback
   };
 };
 
@@ -42,14 +46,19 @@ class VnfSearchTotalCountVisualization extends Component {
     count: React.PropTypes.oneOfType([
       React.PropTypes.string,
       React.PropTypes.number
-    ])
+    ]),
+    enableBusyFeedback: React.PropTypes.bool
   };
 
   render() {
     let {
-          count
+          count,
+          enableBusyFeedback
         } = this.props;
-
+    let componentVisibitliyClassName = 'showContainer';
+    if(enableBusyFeedback){
+      componentVisibitliyClassName = 'hideContainer';
+    }
     let visualizationClass = 'visualizations';
     if (count === null) {
       visualizationClass = 'visualizations hidden';
@@ -61,8 +70,13 @@ class VnfSearchTotalCountVisualization extends Component {
           <div className='visualization-side-by-side-30'>
             <span>&nbsp;</span>
             <h3>{i18n(TOTAL_VNF_COUNT.title)}</h3>
-            <div className='total-box-entity-count'>
-              <span>{count}</span>
+            <div className='spinner'>
+              <ClipLoader color={COLOR_BLUE} loading={enableBusyFeedback} />
+            </div>
+            <div className={componentVisibitliyClassName}>
+              <div className='total-box-entity-count'>
+                <span>{count}</span>
+              </div>
             </div>
           </div>
         </div>

© 2017 ONAP. Copyright © The Linux Foundation ®. All Rights Reserved.
The Linux Foundation has registered trademarks and uses trademarks.
For a list of trademarks of The Linux Foundation, please see our Trademark Usage page.
Linux is a registered trademark of Linus Torvalds.
Privacy Policy and Terms of Use