From f42261a2cd0582e0209018c23816681e146ea97d Mon Sep 17 00:00:00 2001 From: "arul.nambi" Date: Tue, 30 Jan 2018 12:34:34 -0500 Subject: [PATCH 1/1] Implementing user feed back Change-Id: I66196a4a5a319bb9c78c503244c0e78824ac855a Signed-off-by: arul.nambi Issue-ID: AAI-696 --- package.json | 1 + resources/scss/common/_layout.scss | 19 ++++++ src/app/tierSupport/TierSupport.jsx | 78 +++++++++++++--------- src/app/tierSupport/TierSupportActions.js | 18 +++++ src/app/tierSupport/TierSupportConstants.js | 4 +- src/app/tierSupport/TierSupportReducer.js | 10 +++ src/app/vnfSearch/VnfSearchActions.js | 18 +++++ src/app/vnfSearch/VnfSearchConstants.js | 4 +- src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx | 43 +++++++----- src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx | 43 +++++++----- .../VnfSearchOrchestratedStatusVisualization.jsx | 45 ++++++++----- .../vnfSearch/VnfSearchProvStatusVisualization.jsx | 46 ++++++++----- src/app/vnfSearch/VnfSearchReducer.js | 10 +++ .../vnfSearch/VnfSearchTotalCountVisualization.jsx | 28 ++++++-- 14 files changed, 265 insertions(+), 102 deletions(-) diff --git a/package.json b/package.json index 325c418..ddbc889 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/resources/scss/common/_layout.scss b/resources/scss/common/_layout.scss index 1c3bf66..07b5b4c 100644 --- a/resources/scss/common/_layout.scss +++ b/resources/scss/common/_layout.scss @@ -33,3 +33,22 @@ .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 diff --git a/src/app/tierSupport/TierSupport.jsx b/src/app/tierSupport/TierSupport.jsx index 315b6a0..943943f 100644 --- a/src/app/tierSupport/TierSupport.jsx +++ b/src/app/tierSupport/TierSupport.jsx @@ -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 (
- { - onSplitPaneResize(false); - } } - defaultSize={TSUI_NODE_DETAILS_INITIAL_WIDTH} - minSize={TSUI_NODE_DETAILS_MIN_WIDTH} - maxSize={-200} - primary='second'> -
- { - onNodeSelected(nodeData); - }} - nodeButtonSelectedCallback={(selectedMenuId) => { - onNodeMenuSelect(selectedMenuId); - }} - dataOverlayButtons={dataOverlayButtons} - currentlySelectedNodeView={currentNodeButton}/> +
+ +
+
+ { + onSplitPaneResize(false); + } } + defaultSize={TSUI_NODE_DETAILS_INITIAL_WIDTH} + minSize={TSUI_NODE_DETAILS_MIN_WIDTH} + maxSize={-200} + primary='second'> +
+ { + onNodeSelected(nodeData); + }} + nodeButtonSelectedCallback={(selectedMenuId) => { + onNodeMenuSelect(selectedMenuId); + }} + dataOverlayButtons={dataOverlayButtons} + currentlySelectedNodeView={currentNodeButton}/> +
+
+ {currentSelectedMenu} +
+
-
- {currentSelectedMenu} -
-
); } diff --git a/src/app/tierSupport/TierSupportActions.js b/src/app/tierSupport/TierSupportActions.js index ead321e..fc4bcad 100644 --- a/src/app/tierSupport/TierSupportActions.js +++ b/src/app/tierSupport/TierSupportActions.js @@ -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)); }; } diff --git a/src/app/tierSupport/TierSupportConstants.js b/src/app/tierSupport/TierSupportConstants.js index d20325f..d66816e 100644 --- a/src/app/tierSupport/TierSupportConstants.js +++ b/src/app/tierSupport/TierSupportConstants.js @@ -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; diff --git a/src/app/tierSupport/TierSupportReducer.js b/src/app/tierSupport/TierSupportReducer.js index 1560427..c9a4faf 100644 --- a/src/app/tierSupport/TierSupportReducer.js +++ b/src/app/tierSupport/TierSupportReducer.js @@ -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 { diff --git a/src/app/vnfSearch/VnfSearchActions.js b/src/app/vnfSearch/VnfSearchActions.js index 0167962..156f541 100644 --- a/src/app/vnfSearch/VnfSearchActions.js +++ b/src/app/vnfSearch/VnfSearchActions.js @@ -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()); } ); diff --git a/src/app/vnfSearch/VnfSearchConstants.js b/src/app/vnfSearch/VnfSearchConstants.js index 97d7159..200d01f 100644 --- a/src/app/vnfSearch/VnfSearchConstants.js +++ b/src/app/vnfSearch/VnfSearchConstants.js @@ -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 = { diff --git a/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx b/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx index ca6f269..806ab3a 100644 --- a/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx @@ -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 {

{i18n(CHART_NF_ROLE.title)}

- - - - - - - - - +
+ +
+
+ + + + + + + + + +
diff --git a/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx b/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx index 30c6cdc..3f4acf0 100644 --- a/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx @@ -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 {

{i18n(CHART_NF_TYPE.title)}

- - - - - - - - - +
+ +
+
+ + + + + + + + + +
diff --git a/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx b/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx index 1855db7..7cc29d8 100644 --- a/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx @@ -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 {

{i18n(CHART_ORCH_STATUS.title)}

- - - - - - - - - +
+ +
+
+ + + + + + + + + +
diff --git a/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx b/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx index cdf6872..7ef6e9e 100644 --- a/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx @@ -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 {

{i18n(CHART_PROV_STATUS.title)}

- - - - - - - - - +
+ +
+
+ + + + + + + + + +
@@ -90,4 +104,4 @@ class VnfSearchProvStatusVisualization extends Component { } } -export default connect(mapStateToProps)(VnfSearchProvStatusVisualization); +export default connect(mapStateToProps)(VnfSearchProvStatusVisualization); \ No newline at end of file diff --git a/src/app/vnfSearch/VnfSearchReducer.js b/src/app/vnfSearch/VnfSearchReducer.js index 1394f97..afd822c 100644 --- a/src/app/vnfSearch/VnfSearchReducer.js +++ b/src/app/vnfSearch/VnfSearchReducer.js @@ -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, diff --git a/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx b/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx index a2abd7c..553de42 100644 --- a/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx @@ -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 {
 

{i18n(TOTAL_VNF_COUNT.title)}

-
- {count} +
+ +
+
+
+ {count} +
-- 2.16.6