X-Git-Url: https://gerrit.onap.org/r/gitweb?p=aai%2Fsparky-fe.git;a=blobdiff_plain;f=src%2Fapp%2FvnfSearch%2FVnfSearch.jsx;h=d04bbd4a629c4ddfa371d69967c5e3fe83887743;hp=5a35be38a20e9c18b317b3240765f35aa9409131;hb=a7b4b96afee33a2ff458f906742d88cd306ed961;hpb=6ac2e7c0bef5ee478b36181b8bb384119ad3d937 diff --git a/src/app/vnfSearch/VnfSearch.jsx b/src/app/vnfSearch/VnfSearch.jsx index 5a35be3..d04bbd4 100644 --- a/src/app/vnfSearch/VnfSearch.jsx +++ b/src/app/vnfSearch/VnfSearch.jsx @@ -1,62 +1,142 @@ /* - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * ============LICENSE_START=================================================== + * SPARKY (AAI UI service) + * ============================================================================ + * Copyright © 2017 AT&T Intellectual Property. * Copyright © 2017 Amdocs - * ================================================================================ + * All rights reserved. + * ============================================================================ * 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 + * 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. - * ============LICENSE_END========================================================= + * ============LICENSE_END===================================================== * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. */ import React, {Component} from 'react'; import {connect} from 'react-redux'; import { + isEqual, + isEmpty +} from 'lodash'; +import {VerticalFilterBar} from 'vertical-filter-bar'; +import {CollapsibleSlidingPanel} from 'collapsible-sliding-panel'; + +import {setSecondaryTitle} from 'app/MainScreenWrapperActionHelper.js'; +import { + vnfActionTypes, VNF_TITLE, VNFS_ROUTE, - DEFAULT_VNFS_SEARCH_HASH + VNF_SEARCH_FILTER_NAME } from 'app/vnfSearch/VnfSearchConstants.js'; import { - processTotalVnfVisualizationOnSearchChange, - processOrchStatusVisualizationOnSearchChange, - processProvStatusVisualizationOnSearchChange, - setNotificationText + processVnfVisualizationsOnFilterChange, + processVnfFilterPanelCollapse, + setNotificationText, + clearVnfSearchData } from 'app/vnfSearch/VnfSearchActions.js'; import VnfSearchOrchStatusVisualizations from 'app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx'; import VnfSearchProvStatusVisualizations from 'app/vnfSearch/VnfSearchProvStatusVisualization.jsx'; +import VnfSearchNfTypeVisualizations from 'app/vnfSearch/VnfSearchNfTypeVisualization.jsx'; +import VnfSearchNfRoleVisualizations from 'app/vnfSearch/VnfSearchNfRoleVisualization.jsx'; import VnfSearchTotalCountVisualization from 'app/vnfSearch/VnfSearchTotalCountVisualization.jsx'; import i18n from 'utils/i18n/i18n'; -import {changeUrlAddress, buildRouteObj} from 'utils/Routes.js'; +import {changeUrlAddress, buildRouteObjWithFilters} from 'utils/Routes.js'; +import { + getUnifiedFilters, + processFilterSelection, + setNonConvertedFilterValues, + convertNonConvertedValues, + buildFilterValueMap, + setFilterSelectionsToDefaults, + FILTER_BAR_TITLE +} from 'generic-components/filterBar/FilterBarUtils.js'; const mapStateToProps = ({vnfSearch}) => { let { feedbackMsgText = '', - feedbackMsgSeverity = '' + feedbackMsgSeverity = '', + vnfFilters = {}, + selectedFilterValues = {}, + vnfFilterValues = {}, + vnfVisualizationPanelClass = 'collapsible-panel-main-panel', + unifiedFilterValues = {}, + nonConvertedFilters = {} } = vnfSearch; return { feedbackMsgText, - feedbackMsgSeverity + feedbackMsgSeverity, + vnfFilters, + selectedFilterValues, + vnfFilterValues, + vnfVisualizationPanelClass, + unifiedFilterValues, + nonConvertedFilters }; }; let mapActionToProps = (dispatch) => { return { - onReceiveNewParams: (vnfParam) => { - dispatch(processTotalVnfVisualizationOnSearchChange(vnfParam)); - dispatch(processOrchStatusVisualizationOnSearchChange(vnfParam)); - dispatch(processProvStatusVisualizationOnSearchChange(vnfParam)); + onSetViewTitle: (title) => { + dispatch(setSecondaryTitle(title)); + }, + onInitializeVnfSearchFilters: () => { + // first time to the page, need to get the list of available filters + dispatch(getUnifiedFilters(VNF_SEARCH_FILTER_NAME, vnfActionTypes.VNF_SEARCH_FILTERS_RECEIVED)); + }, + onFilterPanelCollapse: (isOpen) => { + // expand/collapse the filter panel + dispatch(processVnfFilterPanelCollapse(isOpen)); + }, + onFilterSelection: (selectedFilters, allFilters) => { + // callback for filter bar whenever a selection is made... need to + // convert and save the selected value(s) + if (Object.keys(allFilters).length > 0) { + // only process the selection if allFilters has values (possible that + // filter bar is sending back the default filter selections before + // we have received the list of available filters i.e. allFilters) + dispatch(processFilterSelection(selectedFilters, allFilters)); + } + }, + onFilterValueChange: (convertedFilterValues) => { + // filter values have been converted, now update the VNF visualizations + dispatch(processVnfVisualizationsOnFilterChange(convertedFilterValues)); + }, + onReceiveNewFilterValueParams: (filterValueString) => { + // new filter values have been received as URL parameters, save the + // non-converted values (later to be converted and sent to filter bar) + // and update the VNF visualizations + let filterValueMap = buildFilterValueMap(filterValueString); + + dispatch(setNonConvertedFilterValues(filterValueMap)); + dispatch(processVnfVisualizationsOnFilterChange(filterValueMap)); + + // incase url param was changed manually, need to update vnfFilterValues + }, + onResetFilterBarToDefaults: (filters, filterValues) => { + dispatch(setFilterSelectionsToDefaults(filters, filterValues)); + }, + onPrepareToUnmount: () => { + // clean things up: + // 1- clear the VNF data + // 2- ensure filter bar is closed + dispatch(clearVnfSearchData()); + dispatch(processVnfFilterPanelCollapse(false)); + }, + onConvertFilterValues: (nonConvertedValues, allFilters, currentlySetFilterValues) => { + // we have saved non-converted filter values received from URL params, + // time to convert them so can update filter bar selections programatically + dispatch(convertNonConvertedValues(nonConvertedValues, allFilters, currentlySetFilterValues)); }, onMessageStateChange: (msgText, msgSeverity) => { dispatch(setNotificationText(msgText, msgSeverity)); @@ -65,16 +145,25 @@ let mapActionToProps = (dispatch) => { }; class vnfSearch extends Component { + static propTypes = { + feedbackMsgText: React.PropTypes.string, + feedbackSeverity: React.PropTypes.string, + vnfFilters: React.PropTypes.object, + selectedFilterValues: React.PropTypes.object, + vnfFilterValues: React.PropTypes.object, + vnfVisualizationPanelClass: React.PropTypes.string, + unifiedFilterValues: React.PropTypes.object, + nonConvertedFilters: React.PropTypes.object + }; + componentWillMount() { + this.props.onSetViewTitle(i18n(VNF_TITLE)); + this.props.onInitializeVnfSearchFilters(); + if (this.props.match && this.props.match.params && - this.props.match.params.vnfParam) { - this.props.onReceiveNewParams(this.props.match.params.vnfParam); - } else { - // render using default search params (hash for "VNFs") - this.props.onReceiveNewParams(DEFAULT_VNFS_SEARCH_HASH); - changeUrlAddress(buildRouteObj(VNFS_ROUTE, DEFAULT_VNFS_SEARCH_HASH), - this.props.history); + this.props.match.params.filters) { + this.props.onReceiveNewFilterValueParams(this.props.match.params.filters); } if (this.props.feedbackMsgText) { @@ -84,42 +173,90 @@ class vnfSearch extends Component { } componentWillReceiveProps(nextProps) { - if (nextProps.match.params.vnfParam) { - if (nextProps.match.params.vnfParam !== - this.props.match.params.vnfParam) { - this.props.onReceiveNewParams(nextProps.match.params.vnfParam); - } - } else if (this.props.match.params.vnfParam) { - // currently on VNF page and somebody has clicked the VNF NavLink - // want to reload the view with the default params (hash for "NFVs") - this.props.onReceiveNewParams(DEFAULT_VNFS_SEARCH_HASH); - changeUrlAddress(buildRouteObj(VNFS_ROUTE, DEFAULT_VNFS_SEARCH_HASH), - this.props.history); - } - if (nextProps.feedbackMsgText && nextProps.feedbackMsgText !== this.props.feedbackMsgText) { this.props.onMessageStateChange(nextProps.feedbackMsgText, nextProps.feedbackMsgSeverity); } + + if (nextProps.vnfFilterValues && + !isEqual(nextProps.vnfFilterValues, this.props.vnfFilterValues) && + this.props.vnfFilters) { + this.props.onFilterValueChange(nextProps.vnfFilterValues); + changeUrlAddress(buildRouteObjWithFilters(VNFS_ROUTE, nextProps.vnfFilterValues), + this.props.history); + } + + if (nextProps.match && + nextProps.match.params && + nextProps.match.params.filters && + !isEqual(nextProps.match.params.filters, this.props.match.params.filters)) { + // added line below to reload the filters if filter changes, this will load new filters + this.props.onInitializeVnfSearchFilters(); + this.props.onReceiveNewFilterValueParams(nextProps.match.params.filters); + } else if (Object.keys(nextProps.nonConvertedFilters).length > 0 && + !isEqual(this.props.nonConvertedFilters, nextProps.nonConvertedFilters)) { + if (Object.keys(this.props.vnfFilters).length > 0) { + this.props.onConvertFilterValues( + nextProps.nonConvertedFilters, this.props.vnfFilters, this.props.vnfFilterValues); + } + } else if ((!nextProps.match || !nextProps.match.params || !nextProps.match.params.filters) && + this.props.match.params.filters && this.props.vnfFilters && this.props.vnfFilterValues) { + // VNF Search navigation button was pressed while the view is still visible ... need to reset + // the filter bar selections to the default values + this.props.onResetFilterBarToDefaults(this.props.vnfFilters, this.props.vnfFilterValues); + } + + if (nextProps.vnfFilters && !isEqual(nextProps.vnfFilters, this.props.vnfFilters) && + Object.keys(this.props.nonConvertedFilters).length > 0) { + // just received list of available filters and there is are nonConvertedFilters (previously + // set from url params), need to convert those values and update the filter bar selections + this.props.onConvertFilterValues( + this.props.nonConvertedFilters, nextProps.vnfFilters, this.props.vnfFilterValues); + } else if (nextProps.vnfFilters && !isEqual(nextProps.vnfFilters, this.props.vnfFilters) && + isEmpty(this.props.vnfFilterValues)) { + // filter bar previously returned the default filter selections (but we didn't have the list + // of available filters at the time, so couldn't do anything. Now receiving the list of + // available filters, so triger the filter selection action in order to load the visualization data + this.props.onResetFilterBarToDefaults(nextProps.vnfFilters, this.props.vnfFilterValues); + } } componentWillUnmount() { - // resetting to default params so on relaunch there will be no - // visibility of old searches - this.props.onReceiveNewParams(DEFAULT_VNFS_SEARCH_HASH); + // set the data to 'NO DATA' so upon return, the view is rendered with + // no data until the request for new data is returned + this.props.onPrepareToUnmount(); + } + + getFilterBar() { + return ( + + this.props.onFilterSelection(selectedFilters, this.props.vnfFilters)} /> ); } render() { + let filterBar = this.getFilterBar(); + return ( -
-
- {i18n(VNF_TITLE)} -
- - - +
+ +
+ + + + + +
+
); }