* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
- * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017 Amdocs
+ * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017-2018 Amdocs
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* See the License for the specific language governing permissions and
* limitations under the License.
* ============LICENSE_END=========================================================
- *
- * ECOMP is a trademark and service mark of AT&T Intellectual Property.
*/
import React, {Component} from 'react';
+import { PropTypes } from 'prop-types';
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 {
+ FilterBarConstants,
+ processFilterSelection,
+ getUnifiedFilters,
+ buildFilterValueMap,
+ setNonConvertedFilterValues,
+ setFilterSelectionsToDefaults,
+ convertNonConvertedValues
+} from 'filter-bar-utils';
+
+import {
+ globalInlineMessageBarActionTypes
+} from 'app/globalInlineMessageBar/GlobalInlineMessageBarConstants.js';
+
+import {
+ UNIFIED_FILTERS_URL,
+ filterBarActionTypes
+} from 'utils/GlobalConstants.js';
const mapStateToProps = ({vnfSearch}) => {
let {
- feedbackMsgText = '',
- feedbackMsgSeverity = ''
- } = vnfSearch;
+ feedbackMsgText = '',
+ 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(UNIFIED_FILTERS_URL, VNF_SEARCH_FILTER_NAME,
+ vnfActionTypes.VNF_SEARCH_FILTERS_RECEIVED, globalInlineMessageBarActionTypes.SET_GLOBAL_MESSAGE));
+ },
+ 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(filterBarActionTypes.NEW_SELECTIONS, 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(filterBarActionTypes.SET_NON_CONVERTED_VALUES, filterValueMap));
+ dispatch(processVnfVisualizationsOnFilterChange(filterValueMap));
+
+ // incase url param was changed manually, need to update vnfFilterValues
+ },
+ onResetFilterBarToDefaults: (filters, filterValues) => {
+ dispatch(setFilterSelectionsToDefaults(filterBarActionTypes.SET_UNIFIED_VALUES,
+ filterBarActionTypes.SET_NON_CONVERTED_VALUES, 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(filterBarActionTypes.SET_CONVERTED_VALUES, nonConvertedValues,
+ allFilters, currentlySetFilterValues));
},
onMessageStateChange: (msgText, msgSeverity) => {
dispatch(setNotificationText(msgText, msgSeverity));
};
};
-class vnfSearch extends Component {
+export class vnfSearch extends Component {
+ static propTypes = {
+ feedbackMsgText: PropTypes.string,
+ feedbackSeverity: PropTypes.string,
+ vnfFilters: PropTypes.object,
+ selectedFilterValues: PropTypes.object,
+ vnfFilterValues: PropTypes.object,
+ vnfVisualizationPanelClass: PropTypes.string,
+ unifiedFilterValues: PropTypes.object,
+ nonConvertedFilters: 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) {
}
componentWillReceiveProps(nextProps) {
- if (nextProps.match.params.vnfParam) {
- if (nextProps.match.params.vnfParam !==
- this.props.match.params.vnfParam) {
- this.props.onReceiveNewParams(nextProps.match.params.vnfParam);
+ 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 (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);
+ } 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.feedbackMsgText &&
- nextProps.feedbackMsgText !==
- this.props.feedbackMsgText) {
- this.props.onMessageStateChange(nextProps.feedbackMsgText,
- nextProps.feedbackMsgSeverity);
+ 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 (
+ <VerticalFilterBar
+ filtersConfig={this.props.vnfFilters}
+ filterValues={this.props.unifiedFilterValues}
+ filterTitle={FilterBarConstants.FILTER_BAR_TITLE}
+ onFilterChange={(selectedFilters) =>
+ this.props.onFilterSelection(selectedFilters, this.props.vnfFilters)} /> );
}
render() {
+ let filterBar = this.getFilterBar();
+
return (
- <div>
- <div className='secondary-header'>
- <span className='secondary-title'>{i18n(VNF_TITLE)}</span>
- </div>
- <VnfSearchTotalCountVisualization />
- <VnfSearchProvStatusVisualizations />
- <VnfSearchOrchStatusVisualizations />
+ <div className='view-container'>
+ <CollapsibleSlidingPanel
+ slidingPanelClassName='collapsible-sliding-panel'
+ slidingPanelClosedClassName='collapsible-sliding-panel-is-closed'
+ expanderHandleClassName='collapsible-sliding-panel-expander'
+ slidingPanelContent={filterBar}>
+ <div className={this.props.vnfVisualizationPanelClass}>
+ <VnfSearchTotalCountVisualization />
+ <VnfSearchProvStatusVisualizations />
+ <VnfSearchOrchStatusVisualizations />
+ <VnfSearchNfTypeVisualizations />
+ <VnfSearchNfRoleVisualizations />
+ </div>
+ </CollapsibleSlidingPanel>
</div>
);
}