2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * Copyright © 2017-2018 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 import React, {Component} from 'react';
22 import {connect} from 'react-redux';
23 import FontAwesome from 'react-fontawesome';
24 import {clearFilters} from 'filter-bar-utils';
25 import Button from 'react-bootstrap/lib/Button.js';
26 import Modal from 'react-bootstrap/lib/Modal.js';
27 import GlobalAutoCompleteSearchBar from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx';
28 import {postAnalyticsData} from 'app/analytics/AnalyticsActions.js';
29 import GlobalInlineMessageBar from 'app/globalInlineMessageBar/GlobalInlineMessageBar.jsx';
30 import {getClearGlobalMessageEvent} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js';
31 import {externalUrlRequest, externalMessageRequest, getSubscriptionPayload} from 'app/contextHandler/ContextHandlerActions.js';
34 } from 'utils/GlobalConstants.js';
39 } from 'react-router-dom';
43 MENU_ITEM_TIER_SUPPORT,
45 } from './MainScreenWrapperConstants.js';
49 clearExtensibleViewData,
51 } from './MainScreenWrapperActionHelper.js';
53 import {clearSuggestionsTextField} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js';
54 import {changeUrlAddress} from 'utils/Routes.js';
55 import extensibleViews from 'resources/views/extensibleViews.json';
58 const mapStateToProps = ({mainWrapper}) => {
61 toggleButtonActive = false,
62 externalRequestFound = {},
64 subscriptionPayload = {},
65 subscriptionEnabled = false
79 const mapActionsToProps = (dispatch) => {
81 onShowMenu: () => dispatch(showMainMenu(true)),
83 dispatch(showMainMenu(false));
85 dispatchAnalyticsData: () => dispatch(
86 postAnalyticsData(document.documentElement.outerHTML.replace('\s+', ''))),
87 onRouteChange: () => {
88 dispatch(getClearGlobalMessageEvent());
89 dispatch(clearSuggestionsTextField());
90 dispatch(clearExtensibleViewData());
91 dispatch(clearFilters(filterBarActionTypes.CLEAR_FILTERS));
92 dispatch(setSecondaryTitle(undefined));
94 onExternalUrlRequest: (urlParamString) => {
95 dispatch(externalUrlRequest(urlParamString));
97 onExternalMessageRecieved: (messageJson) => {
98 dispatch(externalMessageRequest(messageJson));
100 onGetSubscriptionPayload: () => {
101 dispatch(getSubscriptionPayload());
106 class MainScreenHeader extends Component {
108 showMenu: React.PropTypes.bool,
109 toggleButtonActive: React.PropTypes.bool,
110 externalRequestFound: React.PropTypes.object,
111 secondaryTitle: React.PropTypes.string,
112 subscriptionPayload: React.PropTypes.object
115 navigationLinkAndCurrentPathMatch(location, to) {
116 let linkPathElements = to.split('/');
117 let locationElements = location.pathname.split('/');
119 // the element arrays above will have the route at index 1 ... need to
120 // verify if the routes match
121 return locationElements[1] === linkPathElements[1];
124 hasRouteChanged(currentPath, nextPath) {
125 let currentPathParts = currentPath.split('/');
126 let nextPathParts = nextPath.split('/');
128 if (currentPathParts[1] !== nextPathParts[1]) {
135 isValidExternalURL(url) {
136 if(decodeURIComponent(url).indexOf('&') > 0 ) {
143 componentWillMount() {
144 this.props.onGetSubscriptionPayload();
145 if(this.props.match.params.externalUrl !== undefined &&
146 this.isValidExternalURL(this.props.match.params.externalUrl)) {
147 this.props.onExternalUrlRequest(this.props.match.params.externalUrl);
151 componentWillReceiveProps(nextProps) {
152 if (this.props.location &&
153 this.props.location.pathname !==
154 nextProps.location.pathname) {
156 this.props.dispatchAnalyticsData();
158 if (this.hasRouteChanged(this.props.location.pathname,
159 nextProps.location.pathname)) {
160 this.props.onRouteChange();
164 if(nextProps.match.params.externalUrl !== undefined &&
165 nextProps.match.params.externalUrl !== this.props.match.params.externalUrl &&
166 this.isValidExternalURL(nextProps.match.params.externalUrl)) {
167 this.props.onExternalUrlRequest(nextProps.match.params.externalUrl);
169 /* if the externalURL is not valid, we do not add any message as other proper
170 views will get that messages since the route will be this parameter.*/
172 if(this.props.externalRequestFound !== nextProps.externalRequestFound &&
173 nextProps.externalRequestFound !== undefined && nextProps.externalRequestFound.suggestion !== undefined) {
174 changeUrlAddress(nextProps.externalRequestFound.suggestion, nextProps.history);
177 if (nextProps.subscriptionEnabled) {
178 if (nextProps.subscriptionPayload !== this.props.subscriptionPayload &&
179 Object.keys(nextProps.subscriptionPayload).length > 0) {
180 var getWindowUrl = function (url) {
181 var split = url.split('/');
182 return split[0] + '//' + split[2];
184 window.parent.postMessage(
185 JSON.stringify(nextProps.subscriptionPayload),
186 getWindowUrl(document.referrer));
191 receiveMessage(event, $this) {
192 function isJson(str) {
200 if(isJson(event.data)) {
201 let messageData = JSON.parse(event.data);
202 if(isJson(messageData.message)) {
203 $this.props.onExternalMessageRecieved(messageData.message);
208 componentDidMount() {
209 //TODO Move this logic to the component will receive props.
210 //Check if the event lister is available and if the subscription is
211 // enabled before registering for it
212 if(document.referrer) {
214 window.addEventListener('message', function (e) {
215 $this.receiveMessage(e, $this);
219 componentWillUnmount() {
220 if(this.props.subscriptionEnabled) {
222 window.removeEventListener('message', function (e) {
223 $this.receiveMessage(e, $this);
238 let menuOptions = [];
240 const MenuItem = ({label, iconClass, to}) => (
241 <Route path={to} children={({location}) => (
242 <NavLink to={to} onClick={onHideMenu}>
243 <div className={this.navigationLinkAndCurrentPathMatch(location, to) ? 'main-menu-button-active' : 'main-menu-button'}>
244 <div className={iconClass}/>
245 <div className='button-icon'>{label}</div>
251 // add Tier Support view
253 <MenuItem key='schemaMenu' to='/schema' label={MENU_ITEM_TIER_SUPPORT}
254 iconClass='button-icon view-inspect-button-icon'/>
259 <MenuItem key='vnfSearchMenu'
261 label={MENU_ITEM_VNF_SEARCH}
262 iconClass='button-icon vnf-search-button-icon'/>
265 // add all custom view menu options
266 for (let view in extensibleViews) {
267 let shouldDisplayIcon = false;
268 if(extensibleViews[view]['onlyRoute'] === undefined){
269 shouldDisplayIcon = true;
270 } else if(extensibleViews[view]['onlyRoute'] === false){
271 shouldDisplayIcon = true;
273 if(shouldDisplayIcon === true){
275 <MenuItem key={extensibleViews[view]['viewName'] + 'Menu'} to={'/' + extensibleViews[view]['viewName']}
276 label={extensibleViews[view]['displayName']}
277 iconClass={'button-icon ' + extensibleViews[view]['iconClass']}/>
282 let secondaryTitleClass = 'secondary-header';
283 if (secondaryTitle === undefined || secondaryTitle === '') {
284 secondaryTitleClass = secondaryTitleClass + ' hidden';
288 <div className='header'>
291 bsClass={(toggleButtonActive)
292 ? 'toggle-view-button-active'
293 : 'toggle-view-button'}
294 onClick={onShowMenu}>
295 <FontAwesome name='bars'/>
297 <Modal show={showMenu} onHide={onHideMenu}
298 dialogClassName='modal-main-menu'>
303 <span className='application-title'>{AAI_TITLE}</span>
304 <GlobalAutoCompleteSearchBar history={this.props.history}/>
306 <GlobalInlineMessageBar />
307 <div className={secondaryTitleClass}>
308 <span className='secondary-title'>{secondaryTitle}</span>
315 export default connect(mapStateToProps, mapActionsToProps)(MainScreenHeader);