8b574a088dd439315342c8162d0c541abdb266ef
[aai/sparky-fe.git] / src / app / vnfSearch / VnfSearch.jsx
1 /*
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017 Amdocs
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  *
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  */
23 import React, {Component} from 'react';
24 import {connect} from 'react-redux';
25
26 import {
27   isEqual,
28   isEmpty
29 } from 'lodash';
30
31 import {VerticalFilterBar} from 'vertical-filter-bar';
32 import {CollapsibleSlidingPanel} from 'collapsible-sliding-panel';
33
34 import {setSecondaryTitle} from 'app/MainScreenWrapperActionHelper.js';
35 import {
36   vnfActionTypes,
37   VNF_TITLE,
38   VNFS_ROUTE,
39   VNF_SEARCH_FILTER_NAME
40 } from 'app/vnfSearch/VnfSearchConstants.js';
41
42 import {
43   processVnfVisualizationsOnFilterChange,
44   processVnfFilterPanelCollapse,
45   setNotificationText,
46   clearVnfSearchData
47 } from 'app/vnfSearch/VnfSearchActions.js';
48
49 import VnfSearchOrchStatusVisualizations from 'app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx';
50 import VnfSearchProvStatusVisualizations from 'app/vnfSearch/VnfSearchProvStatusVisualization.jsx';
51 import VnfSearchNfTypeVisualizations from 'app/vnfSearch/VnfSearchNfTypeVisualization.jsx';
52 import VnfSearchNfRoleVisualizations from 'app/vnfSearch/VnfSearchNfRoleVisualization.jsx';
53 import VnfSearchTotalCountVisualization from 'app/vnfSearch/VnfSearchTotalCountVisualization.jsx';
54 import i18n from 'utils/i18n/i18n';
55 import {changeUrlAddress, buildRouteObjWithFilters} from 'utils/Routes.js';
56
57 import {
58   FilterBarConstants,
59   processFilterSelection,
60   getUnifiedFilters,
61   buildFilterValueMap,
62   setNonConvertedFilterValues,
63   setFilterSelectionsToDefaults,
64   convertNonConvertedValues
65 } from 'filter-bar-utils';
66
67 import {
68   globalInlineMessageBarActionTypes
69 } from 'app/globalInlineMessageBar/GlobalInlineMessageBarConstants.js';
70
71 import {
72   UNIFIED_FILTERS_URL,
73   filterBarActionTypes
74 } from 'utils/GlobalConstants.js';
75
76 const mapStateToProps = ({vnfSearch}) => {
77   let {
78     feedbackMsgText = '',
79     feedbackMsgSeverity = '',
80     vnfFilters = {},
81     selectedFilterValues = {},
82     vnfFilterValues = {},
83     vnfVisualizationPanelClass = 'collapsible-panel-main-panel',
84     unifiedFilterValues = {},
85     nonConvertedFilters = {}
86   } = vnfSearch;
87
88   return {
89     feedbackMsgText,
90     feedbackMsgSeverity,
91     vnfFilters,
92     selectedFilterValues,
93     vnfFilterValues,
94     vnfVisualizationPanelClass,
95     unifiedFilterValues,
96     nonConvertedFilters
97   };
98 };
99
100 let mapActionToProps = (dispatch) => {
101   return {
102     onSetViewTitle: (title) => {
103       dispatch(setSecondaryTitle(title));
104     },
105     onInitializeVnfSearchFilters: () => {
106       // first time to the page, need to get the list of available filters
107       dispatch(getUnifiedFilters(UNIFIED_FILTERS_URL, VNF_SEARCH_FILTER_NAME,
108         vnfActionTypes.VNF_SEARCH_FILTERS_RECEIVED, globalInlineMessageBarActionTypes.SET_GLOBAL_MESSAGE));
109     },
110     onFilterPanelCollapse: (isOpen) => {
111       // expand/collapse the filter panel
112       dispatch(processVnfFilterPanelCollapse(isOpen));
113     },
114     onFilterSelection: (selectedFilters, allFilters) => {
115       // callback for filter bar whenever a selection is made... need to
116       // convert and save the selected value(s)
117       if (Object.keys(allFilters).length > 0) {
118         // only process the selection if allFilters has values (possible that
119         // filter bar is sending back the default filter selections before
120         // we have received the list of available filters i.e. allFilters)
121         dispatch(processFilterSelection(filterBarActionTypes.NEW_SELECTIONS, selectedFilters, allFilters));
122       }
123     },
124     onFilterValueChange: (convertedFilterValues) => {
125       // filter values have been converted, now update the VNF visualizations
126       dispatch(processVnfVisualizationsOnFilterChange(convertedFilterValues));
127     },
128     onReceiveNewFilterValueParams: (filterValueString) => {
129       // new filter values have been received as URL parameters, save the
130       // non-converted values (later to be converted and sent to filter bar)
131       // and update the VNF visualizations
132       let filterValueMap =  buildFilterValueMap(filterValueString);
133
134       dispatch(setNonConvertedFilterValues(filterBarActionTypes.SET_NON_CONVERTED_VALUES, filterValueMap));
135       dispatch(processVnfVisualizationsOnFilterChange(filterValueMap));
136
137       // incase url param was changed manually, need to update vnfFilterValues
138     },
139     onResetFilterBarToDefaults: (filters, filterValues) => {
140       dispatch(setFilterSelectionsToDefaults(filterBarActionTypes.SET_UNIFIED_VALUES,
141         filterBarActionTypes.SET_NON_CONVERTED_VALUES, filters, filterValues));
142     },
143     onPrepareToUnmount: () => {
144       // clean things up:
145       // 1- clear the VNF data
146       // 2- ensure filter bar is closed
147       dispatch(clearVnfSearchData());
148       dispatch(processVnfFilterPanelCollapse(false));
149     },
150     onConvertFilterValues: (nonConvertedValues, allFilters, currentlySetFilterValues) => {
151       // we have saved non-converted filter values received from URL params,
152       // time to convert them so can update filter bar selections programatically
153       dispatch(convertNonConvertedValues(filterBarActionTypes.SET_CONVERTED_VALUES, nonConvertedValues,
154         allFilters, currentlySetFilterValues));
155     },
156     onMessageStateChange: (msgText, msgSeverity) => {
157       dispatch(setNotificationText(msgText, msgSeverity));
158     }
159   };
160 };
161
162 class vnfSearch extends Component {
163   static propTypes = {
164     feedbackMsgText: React.PropTypes.string,
165     feedbackSeverity: React.PropTypes.string,
166     vnfFilters: React.PropTypes.object,
167     selectedFilterValues: React.PropTypes.object,
168     vnfFilterValues: React.PropTypes.object,
169     vnfVisualizationPanelClass: React.PropTypes.string,
170     unifiedFilterValues: React.PropTypes.object,
171     nonConvertedFilters: React.PropTypes.object
172   };
173
174   componentWillMount() {
175     this.props.onSetViewTitle(i18n(VNF_TITLE));
176     this.props.onInitializeVnfSearchFilters();
177
178     if (this.props.match &&
179       this.props.match.params &&
180       this.props.match.params.filters) {
181       this.props.onReceiveNewFilterValueParams(this.props.match.params.filters);
182     }
183
184     if (this.props.feedbackMsgText) {
185       this.props.onMessageStateChange(this.props.feedbackMsgText,
186         this.props.feedbackMsgSeverity);
187     }
188   }
189
190   componentWillReceiveProps(nextProps) {
191     if (nextProps.feedbackMsgText && nextProps.feedbackMsgText !== this.props.feedbackMsgText) {
192       this.props.onMessageStateChange(nextProps.feedbackMsgText, nextProps.feedbackMsgSeverity);
193     }
194
195     if (nextProps.vnfFilterValues && !isEqual(nextProps.vnfFilterValues, this.props.vnfFilterValues) &&
196       this.props.vnfFilters) {
197       this.props.onFilterValueChange(nextProps.vnfFilterValues);
198       changeUrlAddress(buildRouteObjWithFilters(VNFS_ROUTE, nextProps.vnfFilterValues), this.props.history);
199     }
200
201     if (nextProps.match &&
202       nextProps.match.params &&
203       nextProps.match.params.filters &&
204       !isEqual(nextProps.match.params.filters, this.props.match.params.filters)) {
205       // added line below to reload the filters if filter changes, this will load new filters
206       this.props.onInitializeVnfSearchFilters();
207       this.props.onReceiveNewFilterValueParams(nextProps.match.params.filters);
208     } else if (Object.keys(nextProps.nonConvertedFilters).length > 0 &&
209       !isEqual(this.props.nonConvertedFilters, nextProps.nonConvertedFilters)) {
210       if (Object.keys(this.props.vnfFilters).length > 0) {
211         this.props.onConvertFilterValues(nextProps.nonConvertedFilters, this.props.vnfFilters,
212           this.props.vnfFilterValues);
213       }
214     } else if ((!nextProps.match || !nextProps.match.params || !nextProps.match.params.filters) &&
215       this.props.match.params.filters && this.props.vnfFilters && this.props.vnfFilterValues) {
216       // VNF Search navigation button was pressed while the view is still visible ... need to reset
217       // the filter bar selections to the default values
218       this.props.onResetFilterBarToDefaults(this.props.vnfFilters, this.props.vnfFilterValues);
219     }
220
221     if (nextProps.vnfFilters && !isEqual(nextProps.vnfFilters, this.props.vnfFilters) &&
222       Object.keys(this.props.nonConvertedFilters).length > 0) {
223       // just received list of available filters and there is are nonConvertedFilters (previously
224       // set from url params), need to convert those values and update the filter bar selections
225
226       this.props.onConvertFilterValues(this.props.nonConvertedFilters, nextProps.vnfFilters,
227         this.props.vnfFilterValues);
228
229     } else if (nextProps.vnfFilters && !isEqual(nextProps.vnfFilters, this.props.vnfFilters) &&
230       isEmpty(this.props.vnfFilterValues)) {
231       // filter bar previously returned the default filter selections (but we didn't have the list
232       // of available filters at the time, so couldn't do anything. Now receiving the list of
233       // available filters, so triger the filter selection action in order to load the visualization data
234       this.props.onResetFilterBarToDefaults(nextProps.vnfFilters, this.props.vnfFilterValues);
235     }
236   }
237
238   componentWillUnmount() {
239     // set the data to 'NO DATA' so upon return, the view is rendered with
240     // no data until the request for new data is returned
241     this.props.onPrepareToUnmount();
242   }
243
244   getFilterBar() {
245     return (
246       <VerticalFilterBar
247         filtersConfig={this.props.vnfFilters}
248         filterValues={this.props.unifiedFilterValues}
249         filterTitle={FilterBarConstants.FILTER_BAR_TITLE}
250         onFilterChange={(selectedFilters) =>
251           this.props.onFilterSelection(selectedFilters, this.props.vnfFilters)} />    );
252   }
253
254   render() {
255     let filterBar = this.getFilterBar();
256
257     return (
258       <div className='view-container'>
259         <CollapsibleSlidingPanel
260           slidingPanelClassName='collapsible-sliding-panel'
261           slidingPanelClosedClassName='collapsible-sliding-panel-is-closed'
262           expanderHandleClassName='collapsible-sliding-panel-expander'
263           slidingPanelContent={filterBar}>
264           <div className={this.props.vnfVisualizationPanelClass}>
265             <VnfSearchTotalCountVisualization />
266             <VnfSearchProvStatusVisualizations />
267             <VnfSearchOrchStatusVisualizations />
268             <VnfSearchNfTypeVisualizations />
269             <VnfSearchNfRoleVisualizations />
270           </div>
271         </CollapsibleSlidingPanel>
272       </div>
273     );
274   }
275 }
276 export default connect(mapStateToProps, mapActionToProps)(vnfSearch);