2 * ============LICENSE_START===================================================
3 * SPARKY (AAI UI service)
4 * ============================================================================
5 * Copyright © 2017 AT&T Intellectual Property.
6 * Copyright © 2017 Amdocs
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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=====================================================
22 * ECOMP and OpenECOMP are trademarks
23 * and service marks of AT&T Intellectual Property.
26 import React, {Component} from 'react';
27 import {connect} from 'react-redux';
28 import FontAwesome from 'react-fontawesome';
29 import Button from 'react-bootstrap/lib/Button.js';
30 import Modal from 'react-bootstrap/lib/Modal.js';
31 import GlobalAutoCompleteSearchBar from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx';
32 import {postAnalyticsData} from 'app/analytics/AnalyticsActions.js';
33 import GlobalInlineMessageBar from 'app/GlobalInlineMessageBar/GlobalInlineMessageBar.jsx';
34 import {getClearGlobalMessageEvent} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js';
35 import {externalUrlRequest, externalMessageRequest} from 'app/contextHandler/ContextHandlerActions.js';
40 } from 'react-router-dom';
44 MENU_ITEM_TIER_SUPPORT,
46 } from './MainScreenWrapperConstants.js';
50 clearExtensibleViewData,
52 } from './MainScreenWrapperActionHelper.js';
54 import {clearSuggestionsTextField} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js';
55 import {changeUrlAddress} from 'utils/Routes.js';
56 import extensibleViews from 'resources/views/extensibleViews.json';
57 import {clearFilters} from 'generic-components/filterBar/FilterBarUtils.js';
58 const mapStateToProps = ({mainWrapper}) => {
61 toggleButtonActive = false,
62 externalRequestFound = {},
75 const mapActionsToProps = (dispatch) => {
77 onShowMenu: () => dispatch(showMainMenu(true)),
79 dispatch(showMainMenu(false));
81 dispatchAnalyticsData: () => dispatch(
82 postAnalyticsData(document.documentElement.outerHTML.replace('\s+', ''))),
83 onRouteChange: () => {
84 dispatch(getClearGlobalMessageEvent());
85 dispatch(clearSuggestionsTextField());
86 dispatch(clearExtensibleViewData());
87 dispatch(clearFilters());
88 dispatch(setSecondaryTitle(undefined));
90 onExternalUrlRequest: (urlParamString) => {
91 dispatch(externalUrlRequest(urlParamString));
93 onExternalMessageRecieved: (messageJson) => {
94 dispatch(externalMessageRequest(messageJson));
99 class MainScreenHeader extends Component {
101 showMenu: React.PropTypes.bool,
102 toggleButtonActive: React.PropTypes.bool,
103 externalRequestFound: React.PropTypes.object,
104 secondaryTitle: React.PropTypes.string
107 navigationLinkAndCurrentPathMatch(location, to) {
108 let linkPathElements = to.split('/');
109 let locationElements = location.pathname.split('/');
111 // the element arrays above will have the route at index 1 ... need to
112 // verify if the routes match
113 return locationElements[1] === linkPathElements[1];
116 hasRouteChanged(currentPath, nextPath) {
117 let currentPathParts = currentPath.split('/');
118 let nextPathParts = nextPath.split('/');
120 if (currentPathParts[1] !== nextPathParts[1]) {
126 isValidExternalURL(url) {
127 if(decodeURIComponent(url).indexOf('&') > 0 ) {
133 componentWillMount() {
134 if(this.props.match.params.externalUrl !== undefined &&
135 this.isValidExternalURL(this.props.match.params.externalUrl)) {
136 this.props.onExternalUrlRequest(this.props.match.params.externalUrl);
139 componentWillReceiveProps(nextProps) {
140 if (this.props.location &&
141 this.props.location.pathname !==
142 nextProps.location.pathname) {
144 this.props.dispatchAnalyticsData();
146 if (this.hasRouteChanged(this.props.location.pathname,
147 nextProps.location.pathname)) {
148 this.props.onRouteChange();
152 if(nextProps.match.params.externalUrl !== undefined &&
153 nextProps.match.params.externalUrl !== this.props.match.params.externalUrl &&
154 this.isValidExternalURL(nextProps.match.params.externalUrl)) {
155 this.props.onExternalUrlRequest(nextProps.match.params.externalUrl);
157 /* if the externalURL is not valid, we do not add any message as other proper
158 views will get that messages since the route will be this parameter.*/
160 if(this.props.externalRequestFound !== nextProps.externalRequestFound &&
161 nextProps.externalRequestFound !== undefined && nextProps.externalRequestFound.suggestion !== undefined) {
162 changeUrlAddress(nextProps.externalRequestFound.suggestion, nextProps.history);
166 receiveMessage(event) {
167 function isJson(str) {
175 let messageData = event.data.message;
176 if(isJson(messageData)) {
177 this.props.onExternalMessageRecieved(JSON.parse(messageData));
180 componentDidMount() {
181 window.addEventListener('message', this.receiveMessage, false);
183 componentWillUnmount() {
184 window.removeEventListener('message', this.receiveMessage);
196 let menuOptions = [];
198 const MenuItem = ({label, iconClass, to}) => (
199 <Route path={to} children={({location}) => (
200 <NavLink to={to} onClick={onHideMenu}>
201 <div className={this.navigationLinkAndCurrentPathMatch(location, to) ? 'main-menu-button-active' : 'main-menu-button'}>
202 <div className={iconClass}/>
203 <div className='button-icon'>{label}</div>
209 // add Tier Support view
211 <MenuItem key='schemaMenu' to='/schema' label={MENU_ITEM_TIER_SUPPORT}
212 iconClass='button-icon view-inspect-button-icon'/>
217 <MenuItem key='vnfSearchMenu'
219 label={MENU_ITEM_VNF_SEARCH}
220 iconClass='button-icon vnf-search-button-icon'/>
223 // add all custom view menu options
224 for (let view in extensibleViews) {
226 <MenuItem key={extensibleViews[view]['viewName'] + 'Menu'} to={'/' + extensibleViews[view]['viewName']}
227 label={extensibleViews[view]['displayName']}
228 iconClass={'button-icon ' + extensibleViews[view]['iconClass']}/>
232 let secondaryTitleClass = 'secondary-header';
233 if (secondaryTitle === undefined || secondaryTitle === '') {
234 secondaryTitleClass = secondaryTitleClass + ' hidden';
238 <div className='header'>
241 bsClass={(toggleButtonActive)
242 ? 'toggle-view-button-active'
243 : 'toggle-view-button'}
244 onClick={onShowMenu}>
245 <FontAwesome name='bars'/>
247 <Modal show={showMenu} onHide={onHideMenu}
248 dialogClassName='modal-main-menu'>
253 <span className='application-title'>{AAI_TITLE}</span>
254 <GlobalAutoCompleteSearchBar history={this.props.history}/>
256 <GlobalInlineMessageBar />
257 <div className={secondaryTitleClass}>
258 <span className='secondary-title'>{secondaryTitle}</span>
265 export default connect(mapStateToProps, mapActionsToProps)(MainScreenHeader);