2 * ============LICENSE_START=======================================================
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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=========================================================
21 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
23 import React, {Component} from 'react';
24 import {connect} from 'react-redux';
25 import FontAwesome from 'react-fontawesome';
26 import Button from 'react-bootstrap/lib/Button.js';
27 import Modal from 'react-bootstrap/lib/Modal.js';
28 import GlobalAutoCompleteSearchBar from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx';
29 import {postAnalyticsData} from 'app/analytics/AnalyticsActions.js';
30 import GlobalInlineMessageBar from 'app/GlobalInlineMessageBar/GlobalInlineMessageBar.jsx';
31 import {getClearGlobalMessageEvent} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js';
32 import {externalUrlRequest, externalMessageRequest} from 'app/contextHandler/ContextHandlerActions.js';
37 } from 'react-router-dom';
41 MENU_ITEM_TIER_SUPPORT,
43 } from './MainScreenWrapperConstants.js';
47 clearExtensibleViewData,
49 } from './MainScreenWrapperActionHelper.js';
51 import {clearSuggestionsTextField} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js';
52 import {changeUrlAddress} from 'utils/Routes.js';
53 import extensibleViews from 'resources/views/extensibleViews.json';
54 import {clearFilters} from 'generic-components/filterBar/FilterBarUtils.js';
55 const mapStateToProps = ({mainWrapper}) => {
58 toggleButtonActive = false,
59 externalRequestFound = {},
72 const mapActionsToProps = (dispatch) => {
74 onShowMenu: () => dispatch(showMainMenu(true)),
76 dispatch(showMainMenu(false));
78 dispatchAnalyticsData: () => dispatch(
79 postAnalyticsData(document.documentElement.outerHTML.replace('\s+', ''))),
80 onRouteChange: () => {
81 dispatch(getClearGlobalMessageEvent());
82 dispatch(clearSuggestionsTextField());
83 dispatch(clearExtensibleViewData());
84 dispatch(clearFilters());
85 dispatch(setSecondaryTitle(undefined));
87 onExternalUrlRequest: (urlParamString) => {
88 dispatch(externalUrlRequest(urlParamString));
90 onExternalMessageRecieved: (messageJson) => {
91 dispatch(externalMessageRequest(messageJson));
96 class MainScreenHeader extends Component {
98 showMenu: React.PropTypes.bool,
99 toggleButtonActive: React.PropTypes.bool,
100 externalRequestFound: React.PropTypes.object,
101 secondaryTitle: React.PropTypes.string
104 navigationLinkAndCurrentPathMatch(location, to) {
105 let linkPathElements = to.split('/');
106 let locationElements = location.pathname.split('/');
108 // the element arrays above will have the route at index 1 ... need to
109 // verify if the routes match
110 return locationElements[1] === linkPathElements[1];
113 hasRouteChanged(currentPath, nextPath) {
114 let currentPathParts = currentPath.split('/');
115 let nextPathParts = nextPath.split('/');
117 if (currentPathParts[1] !== nextPathParts[1]) {
123 isValidExternalURL(url) {
124 if(decodeURIComponent(url).indexOf('&') > 0 ) {
130 componentWillMount() {
131 if(this.props.match.params.externalUrl !== undefined &&
132 this.isValidExternalURL(this.props.match.params.externalUrl)) {
133 this.props.onExternalUrlRequest(this.props.match.params.externalUrl);
136 componentWillReceiveProps(nextProps) {
137 if (this.props.location &&
138 this.props.location.pathname !==
139 nextProps.location.pathname) {
141 this.props.dispatchAnalyticsData();
143 if (this.hasRouteChanged(this.props.location.pathname,
144 nextProps.location.pathname)) {
145 this.props.onRouteChange();
149 if(nextProps.match.params.externalUrl !== undefined &&
150 nextProps.match.params.externalUrl !== this.props.match.params.externalUrl &&
151 this.isValidExternalURL(nextProps.match.params.externalUrl)) {
152 this.props.onExternalUrlRequest(nextProps.match.params.externalUrl);
154 /* if the externalURL is not valid, we do not add any message as other proper
155 views will get that messages since the route will be this parameter.*/
157 if(this.props.externalRequestFound !== nextProps.externalRequestFound &&
158 nextProps.externalRequestFound !== undefined && nextProps.externalRequestFound.suggestion !== undefined) {
159 changeUrlAddress(nextProps.externalRequestFound.suggestion, nextProps.history);
163 receiveMessage(event) {
164 function isJson(str) {
172 let messageData = event.data.message;
173 if(isJson(messageData)) {
174 this.props.onExternalMessageRecieved(JSON.parse(messageData));
177 componentDidMount() {
178 window.addEventListener('message', this.receiveMessage, false);
180 componentWillUnmount() {
181 window.removeEventListener('message', this.receiveMessage);
193 let menuOptions = [];
195 const MenuItem = ({label, iconClass, to}) => (
196 <Route path={to} children={({location}) => (
197 <NavLink to={to} onClick={onHideMenu}>
198 <div className={this.navigationLinkAndCurrentPathMatch(location, to) ? 'main-menu-button-active' : 'main-menu-button'}>
199 <div className={iconClass}/>
200 <div className='button-icon'>{label}</div>
206 // add Tier Support view
208 <MenuItem key='schemaMenu' to='/schema' label={MENU_ITEM_TIER_SUPPORT}
209 iconClass='button-icon view-inspect-button-icon'/>
214 <MenuItem key='vnfSearchMenu'
216 label={MENU_ITEM_VNF_SEARCH}
217 iconClass='button-icon vnf-search-button-icon'/>
220 // add all custom view menu options
221 for (let view in extensibleViews) {
223 <MenuItem key={extensibleViews[view]['viewName'] + 'Menu'} to={'/' + extensibleViews[view]['viewName']}
224 label={extensibleViews[view]['displayName']}
225 iconClass={'button-icon ' + extensibleViews[view]['iconClass']}/>
229 let secondaryTitleClass = 'secondary-header';
230 if (secondaryTitle === undefined || secondaryTitle === '') {
231 secondaryTitleClass = secondaryTitleClass + ' hidden';
235 <div className='header'>
238 bsClass={(toggleButtonActive)
239 ? 'toggle-view-button-active'
240 : 'toggle-view-button'}
241 onClick={onShowMenu}>
242 <FontAwesome name='bars'/>
244 <Modal show={showMenu} onHide={onHideMenu}
245 dialogClassName='modal-main-menu'>
250 <span className='application-title'>{AAI_TITLE}</span>
251 <GlobalAutoCompleteSearchBar history={this.props.history}/>
253 <GlobalInlineMessageBar />
254 <div className={secondaryTitleClass}>
255 <span className='secondary-title'>{secondaryTitle}</span>
262 export default connect(mapStateToProps, mapActionsToProps)(MainScreenHeader);