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