diff options
63 files changed, 3763 insertions, 855 deletions
diff --git a/src/app/AppStore.js b/src/app/AppStore.js index 0270b47..0a49c68 100644 --- a/src/app/AppStore.js +++ b/src/app/AppStore.js @@ -1,25 +1,28 @@ /* - * ============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 {combineReducers, createStore, compose, applyMiddleware} from 'redux'; import thunkMiddleware from 'redux-thunk'; import GlobalAutoCompleteSearchBarReducer from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarReducer.js'; @@ -28,7 +31,10 @@ import MainScreenWrapperReducer from './MainScreenWrapperReducer.js'; import InventoryReducer from './inventory/InventoryReducer.js'; import DynamicViewLoaderReducer from 'generic-components/dynamicViewLoader/DynamicViewLoaderReducer.js'; import VnfSearchReducer from './vnfSearch/VnfSearchReducer.js'; -import GlobalInlineMessageBarReducer from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarReducer.js'; +import GlobalInlineMessageBarReducer from 'app/globalInlineMessageBar/GlobalInlineMessageBarReducer.js'; +import ExtensibilityReducer from 'app/extensibility/ExtensibilityReducer.js'; + + function createCompose() { return window.devToolsExtension @@ -45,7 +51,8 @@ export const storeCreator = (initialState) => createStore( inventoryReducer: InventoryReducer, dynamicViewReducer: DynamicViewLoaderReducer, vnfSearch: VnfSearchReducer, - globalInlineMessageBar: GlobalInlineMessageBarReducer + globalInlineMessageBar: GlobalInlineMessageBarReducer, + extensibility: ExtensibilityReducer }), initialState, createCompose() diff --git a/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js index 1447f68..7b41644 100644 --- a/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js +++ b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js @@ -1,28 +1,30 @@ /* - * ============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 { globalInlineMessageBarActionTypes -} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarConstants.js'; +} from 'app/globalInlineMessageBar/GlobalInlineMessageBarConstants.js'; export function getSetGlobalMessageEvent(msgText, msgSeverity) { return { diff --git a/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarReducer.js b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarReducer.js index 48fdcdf..93dde7e 100644 --- a/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarReducer.js +++ b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarReducer.js @@ -1,28 +1,30 @@ /* - * ============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 { globalInlineMessageBarActionTypes -} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarConstants.js'; +} from 'app/globalInlineMessageBar/GlobalInlineMessageBarConstants.js'; export default (state = {}, action) => { switch (action.type) { diff --git a/src/app/MainScreenHeader.jsx b/src/app/MainScreenHeader.jsx index af71a97..856a08d 100644 --- a/src/app/MainScreenHeader.jsx +++ b/src/app/MainScreenHeader.jsx @@ -1,25 +1,28 @@ /* - * ============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 FontAwesome from 'react-fontawesome'; @@ -28,7 +31,8 @@ import Modal from 'react-bootstrap/lib/Modal.js'; import GlobalAutoCompleteSearchBar from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx'; import {postAnalyticsData} from 'app/analytics/AnalyticsActions.js'; import GlobalInlineMessageBar from 'app/GlobalInlineMessageBar/GlobalInlineMessageBar.jsx'; -import {getClearGlobalMessageEvent} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js'; +import {getClearGlobalMessageEvent} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js'; +import {externalUrlRequest, externalMessageRequest} from 'app/contextHandler/ContextHandlerActions.js'; import { Route, @@ -42,25 +46,32 @@ import { } from './MainScreenWrapperConstants.js'; import { - showMainMenu + showMainMenu, + clearExtensibleViewData, + setSecondaryTitle } from './MainScreenWrapperActionHelper.js'; import {clearSuggestionsTextField} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js'; - -import customViews from 'resources/views/customViews.json'; - +import {changeUrlAddress} from 'utils/Routes.js'; +import extensibleViews from 'resources/views/extensibleViews.json'; +import {clearFilters} from 'generic-components/filterBar/FilterBarUtils.js'; const mapStateToProps = ({mainWrapper}) => { let { - showMenu = false, - toggleButtonActive = false - } = mainWrapper; + showMenu = false, + toggleButtonActive = false, + externalRequestFound = {}, + secondaryTitle = '' + } = mainWrapper; return { showMenu, - toggleButtonActive + toggleButtonActive, + externalRequestFound, + secondaryTitle }; }; + const mapActionsToProps = (dispatch) => { return { onShowMenu: () => dispatch(showMainMenu(true)), @@ -72,6 +83,15 @@ const mapActionsToProps = (dispatch) => { onRouteChange: () => { dispatch(getClearGlobalMessageEvent()); dispatch(clearSuggestionsTextField()); + dispatch(clearExtensibleViewData()); + dispatch(clearFilters()); + dispatch(setSecondaryTitle(undefined)); + }, + onExternalUrlRequest: (urlParamString) => { + dispatch(externalUrlRequest(urlParamString)); + }, + onExternalMessageRecieved: (messageJson) => { + dispatch(externalMessageRequest(messageJson)); } }; }; @@ -79,7 +99,9 @@ const mapActionsToProps = (dispatch) => { class MainScreenHeader extends Component { static propTypes = { showMenu: React.PropTypes.bool, - toggleButtonActive: React.PropTypes.bool + toggleButtonActive: React.PropTypes.bool, + externalRequestFound: React.PropTypes.object, + secondaryTitle: React.PropTypes.string }; navigationLinkAndCurrentPathMatch(location, to) { @@ -101,10 +123,23 @@ class MainScreenHeader extends Component { return false; } } - + isValidExternalURL(url) { + if(decodeURIComponent(url).indexOf('&') > 0 ) { + return true; + } else { + return false; + } + } + componentWillMount() { + if(this.props.match.params.externalUrl !== undefined && + this.isValidExternalURL(this.props.match.params.externalUrl)) { + this.props.onExternalUrlRequest(this.props.match.params.externalUrl); + } + } componentWillReceiveProps(nextProps) { if (this.props.location && - this.props.location.pathname !== nextProps.location.pathname) { + this.props.location.pathname !== + nextProps.location.pathname) { // update analytics this.props.dispatchAnalyticsData(); @@ -113,15 +148,50 @@ class MainScreenHeader extends Component { this.props.onRouteChange(); } } + + if(nextProps.match.params.externalUrl !== undefined && + nextProps.match.params.externalUrl !== this.props.match.params.externalUrl && + this.isValidExternalURL(nextProps.match.params.externalUrl)) { + this.props.onExternalUrlRequest(nextProps.match.params.externalUrl); + } + /* if the externalURL is not valid, we do not add any message as other proper + views will get that messages since the route will be this parameter.*/ + + if(this.props.externalRequestFound !== nextProps.externalRequestFound && + nextProps.externalRequestFound !== undefined && nextProps.externalRequestFound.suggestion !== undefined) { + changeUrlAddress(nextProps.externalRequestFound.suggestion, nextProps.history); + } + } + + receiveMessage(event) { + function isJson(str) { + try { + JSON.parse(str); + } catch (e) { + return false; + } + return true; + } + let messageData = event.data.message; + if(isJson(messageData)) { + this.props.onExternalMessageRecieved(JSON.parse(messageData)); + } + } + componentDidMount() { + window.addEventListener('message', this.receiveMessage, false); + } + componentWillUnmount() { + window.removeEventListener('message', this.receiveMessage); } render() { let { - showMenu, - onShowMenu, - onHideMenu, - toggleButtonActive - } = this.props; + showMenu, + onShowMenu, + onHideMenu, + toggleButtonActive, + secondaryTitle + } = this.props; let menuOptions = []; @@ -138,54 +208,56 @@ class MainScreenHeader extends Component { // add Tier Support view menuOptions.push( - <MenuItem to='/viewInspect' label={MENU_ITEM_TIER_SUPPORT} + <MenuItem key='schemaMenu' to='/schema' label={MENU_ITEM_TIER_SUPPORT} iconClass='button-icon view-inspect-button-icon'/> ); // add VNF view - // 2172a3c25ae56e4995038ffbc1f055692bfc76c0b8ceda1205bc745a9f7a805d is - // the hash for 'VNFs' ... ensures VNF Search screen defaults to the - // aggregate VNF results menuOptions.push( - <MenuItem - to='/vnfSearch/2172a3c25ae56e4995038ffbc1f055692bfc76c0b8ceda1205bc745a9f7a805d' + <MenuItem key='vnfSearchMenu' + to='/vnfSearch' label={MENU_ITEM_VNF_SEARCH} iconClass='button-icon vnf-search-button-icon'/> ); // add all custom view menu options - for (let view in customViews) { + for (let view in extensibleViews) { menuOptions.push( - <MenuItem to={customViews[view]['viewName']} - label={customViews[view]['displayName']} - iconClass='button-icon inventory-button-icon'/> + <MenuItem key={extensibleViews[view]['viewName'] + 'Menu'} to={'/' + extensibleViews[view]['viewName']} + label={extensibleViews[view]['displayName']} + iconClass={'button-icon ' + extensibleViews[view]['iconClass']}/> ); } + let secondaryTitleClass = 'secondary-header'; + if (secondaryTitle === undefined || secondaryTitle === '') { + secondaryTitleClass = secondaryTitleClass + ' hidden'; + } + return ( - <div> - <div className='header'> - <div> - <Button - bsClass={(toggleButtonActive) - ? 'toggle-view-button-active' - : 'toggle-view-button'} - onClick={onShowMenu}> - <FontAwesome name='bars'/> - </Button> - <Modal show={showMenu} onHide={onHideMenu} - dialogClassName='modal-main-menu'> - <Modal.Body> - {menuOptions} - </Modal.Body> - </Modal> - <span className='application-title'>{AAI_TITLE}</span> - <GlobalAutoCompleteSearchBar history={this.props.history}/> - </div> - <GlobalInlineMessageBar /> + <div className='header'> + <div> + <Button + bsClass={(toggleButtonActive) + ? 'toggle-view-button-active' + : 'toggle-view-button'} + onClick={onShowMenu}> + <FontAwesome name='bars'/> + </Button> + <Modal show={showMenu} onHide={onHideMenu} + dialogClassName='modal-main-menu'> + <Modal.Body> + {menuOptions} + </Modal.Body> + </Modal> + <span className='application-title'>{AAI_TITLE}</span> + <GlobalAutoCompleteSearchBar history={this.props.history}/> + </div> + <GlobalInlineMessageBar /> + <div className={secondaryTitleClass}> + <span className='secondary-title'>{secondaryTitle}</span> </div> </div> - ); } } diff --git a/src/app/MainScreenWrapper.jsx b/src/app/MainScreenWrapper.jsx index 054450b..b5ce3bf 100644 --- a/src/app/MainScreenWrapper.jsx +++ b/src/app/MainScreenWrapper.jsx @@ -1,34 +1,36 @@ /* - * ============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 * as Extensibility from './extensibility/index.js'; import TierSupport from './tierSupport/TierSupport.jsx'; import VnfSearch from './vnfSearch/VnfSearch.jsx'; import MainScreenHeader from './MainScreenHeader.jsx'; +import {decryptParamsForView, changeUrlAddress} from 'utils/Routes.js'; -import DynamicViewLoader from - 'generic-components/dynamicViewLoader/dynamicViewLoader.jsx'; import { Route, @@ -38,26 +40,36 @@ import { } from 'react-router-dom'; import { - windowResize + windowResize, + extensibleViewNetworkCallback, + extensibleViewMessageCallback } from './MainScreenWrapperActionHelper.js'; -import customViews from 'resources/views/customViews.json'; +import extensibleViews from 'resources/views/extensibleViews.json'; const mapStateToProps = ({mainWrapper}) => { let { - showMenu = false, - toggleButtonActive = false - } = mainWrapper; + showMenu = false, + toggleButtonActive = false, + extensibleViewNetworkCallbackData = {} + } = mainWrapper; return { showMenu, - toggleButtonActive + toggleButtonActive, + extensibleViewNetworkCallbackData }; }; const mapActionsToProps = (dispatch) => { return { - onWindowSizeChange: () => dispatch(windowResize()) + onWindowSizeChange: () => dispatch(windowResize()), + onExtensibleViewNetworkCallback: (apiUrl,body,viewName,curViewData) => { + dispatch(extensibleViewNetworkCallback(apiUrl,body,viewName,curViewData)); + }, + onExtensibleViewMessageCallback: (message, messageSevirity) => { + dispatch(extensibleViewMessageCallback(message, messageSevirity)); + } }; }; @@ -68,28 +80,62 @@ class MainScreenWrapper extends Component { window.addEventListener('resize', () => { this.props.onWindowSizeChange(); }); + } + render() { + + const { + onExtensibleViewNetworkCallback, + extensibleViewNetworkCallbackData, + onExtensibleViewMessageCallback + } = this.props; + let customViewList = []; + extensibleViews.forEach(function(view,key){ + var renderComponent = (props) => { + let viewParams = {}; + if(props.match.params.extensibleViewParams !== undefined) { + viewParams = decryptParamsForView(props.match.params.extensibleViewParams); + } + + if (Extensibility.default.hasOwnProperty(view.componentName)) { + let Component = Extensibility.default[view.componentName]; + return ( + <Component + {...props} + networkingCallback={(apiUrl, body, paramName,curViewData) => { + onExtensibleViewNetworkCallback(apiUrl, body, paramName, curViewData); + }} + messagingCallback ={(message, messageSevirity) => { + onExtensibleViewMessageCallback(message, messageSevirity); + }} + changeRouteCallback = {(routeParam, historyObj) => { + changeUrlAddress(routeParam, historyObj); + }} + viewName={view.displayName} + viewData={extensibleViewNetworkCallbackData} + viewParams={viewParams}/> + ); + } + }; - // add all custom views - for (let view in customViews) { customViewList.push( - <Route path={'/' + customViews[view]['viewName']} - component={DynamicViewLoader}/> + <Route key={extensibleViews[key]['viewName'] + 'Route'} path={'/' + extensibleViews[key]['viewName'] + '/:extensibleViewParams?' } + render={renderComponent}/> ); - } + }); return ( <Router> - <div> + <div className='main-app-container'> <Switch> - <Redirect from='/' exact to='/viewInspect'/> + <Redirect from='/' exact to='/schema'/> </Switch> - <Route path='/' component={MainScreenHeader}/> - <Route path='/viewInspect/:viParam?' component={TierSupport}/> - <Route path='/vnfSearch/:vnfParam?' component={VnfSearch}/> + <Route key='MainScreenHeaderRoute' path='/:externalUrl?' component={MainScreenHeader}/> + <Route key='TierSupportRoue' path='/schema/:viParam?' component={TierSupport}/> + <Route key='VnfSearchRoute' path='/vnfSearch/:filters?' component={VnfSearch}/> {customViewList} </div> </Router> diff --git a/src/app/MainScreenWrapperActionHelper.js b/src/app/MainScreenWrapperActionHelper.js index 7918ec9..bcf78e3 100644 --- a/src/app/MainScreenWrapperActionHelper.js +++ b/src/app/MainScreenWrapperActionHelper.js @@ -1,26 +1,44 @@ /* - * ============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 {aaiActionTypes} from './MainScreenWrapperConstants.js'; +import { + POST, + POST_HEADER, + BASE_URL, + ERROR_RETRIEVING_DATA +} from 'app/networking/NetworkConstants.js'; +import { + MESSAGE_LEVEL_DANGER +} from 'utils/GlobalConstants.js'; +import {fetchRequestObj} from 'app/networking/NetworkCalls.js'; + +import { + getSetGlobalMessageEvent, + getClearGlobalMessageEvent +} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js'; function createWindowSizeChangeEvent() { return { @@ -48,3 +66,71 @@ export function showMainMenu(show) { dispatch(createShowMenuEvent(show)); }; } + +function createViewDataFoundEvent(viewData, paramName, curViewData) { + var obj = {}; + obj['data'] = {}; + obj['data']['paramName'] = paramName; + obj['data']['viewData'] = viewData; + obj['data']['curViewData'] = curViewData; + obj['type'] = aaiActionTypes.EXTENSIBLE_VIEW_NETWORK_CALLBACK_RESPONSE_RECEIVED; + + return obj; +} + +function extensibleViewData(dataFetchRequest, paramName, curViewData) { + return dispatch => { + return dataFetchRequest().then( + (response) => { + return response.json(); + } + ).then( + (responseJson) => { + dispatch(createViewDataFoundEvent(responseJson, paramName, curViewData)); + }).catch( + () => { + dispatch(getSetGlobalMessageEvent(ERROR_RETRIEVING_DATA, MESSAGE_LEVEL_DANGER)); + dispatch(createViewDataFoundEvent({}, paramName, curViewData)); + //To-do: If need to send a flag later on to the view, add a function to have the flag + }); + }; +} + +export function extensibleViewNetworkCallback(urlApi, postBody, paramName, curViewData) { + + let dataFetchRequest = + () => fetchRequestObj(BASE_URL + urlApi, POST, + POST_HEADER, postBody); + + + return dispatch => { + dispatch(extensibleViewData(dataFetchRequest, paramName, curViewData)); + }; +} + +export function extensibleViewMessageCallback(msgText, msgSeverity) { + if (msgText.length > 0) { + return dispatch => { + dispatch( + getSetGlobalMessageEvent(msgText, msgSeverity)); + }; + } else { + return dispatch => { + dispatch(getClearGlobalMessageEvent()); + }; + } +} + +export function clearExtensibleViewData() { + return { + type: aaiActionTypes.EXTENSIBLE_VIEW_NETWORK_CALLBACK_CLEAR_DATA, + data: {} + }; +} + +export function setSecondaryTitle(title) { + return { + type: aaiActionTypes.SET_SECONDARY_TITLE, + data: title + }; +} diff --git a/src/app/MainScreenWrapperConstants.js b/src/app/MainScreenWrapperConstants.js index 5b69cc2..36efb1f 100644 --- a/src/app/MainScreenWrapperConstants.js +++ b/src/app/MainScreenWrapperConstants.js @@ -1,31 +1,37 @@ /* - * ============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 keyMirror from 'utils/KeyMirror.js'; export const aaiActionTypes = keyMirror({ SET_CURRENT_SCREEN: null, AAI_WINDOW_RESIZE: null, - AAI_SHOW_MENU: null + AAI_SHOW_MENU: null, + EXTENSIBLE_VIEW_NETWORK_CALLBACK_RESPONSE_RECEIVED: null, + EXTENSIBLE_VIEW_NETWORK_CALLBACK_CLEAR_DATA: null, + SET_SECONDARY_TITLE: null }); export const screens = keyMirror({ diff --git a/src/app/MainScreenWrapperReducer.js b/src/app/MainScreenWrapperReducer.js index 8314115..3d3098a 100644 --- a/src/app/MainScreenWrapperReducer.js +++ b/src/app/MainScreenWrapperReducer.js @@ -1,35 +1,74 @@ /* - * ============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 {aaiActionTypes} from './MainScreenWrapperConstants.js'; +import { + globalAutoCompleteSearchBarActionTypes +} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js'; +import { + contextHandlerActionTypes +} from 'app/contextHandler/ContextHandlerConstants.js'; export default (state = {}, action) => { - if (action.type === aaiActionTypes.AAI_SHOW_MENU) { - return { - ...state, - showMenu: action.data.showMenu, - toggleButtonActive: action.data.showMenu // if showing menu, then toggle + switch (action.type) { + case aaiActionTypes.AAI_SHOW_MENU: + return { + ...state, + showMenu: action.data.showMenu, + toggleButtonActive: action.data.showMenu // if showing menu, then toggle // is active - }; + }; + case aaiActionTypes.EXTENSIBLE_VIEW_NETWORK_CALLBACK_RESPONSE_RECEIVED: + let obj = {...state}; + obj['extensibleViewNetworkCallbackData'] = {}; + obj['extensibleViewNetworkCallbackData'][action.data.paramName] = action.data.viewData; + // If there are some current viewData that need to be kept: + for(var vData in action.data.curViewData) { + obj['extensibleViewNetworkCallbackData'][vData] = action.data.curViewData[vData]; + } + return obj; + case aaiActionTypes.EXTENSIBLE_VIEW_NETWORK_CALLBACK_CLEAR_DATA: + return { + ...state, + extensibleViewNetworkCallbackData : {} + }; + case globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT: + return { + ...state, + extensibleViewNetworkCallbackData: {clearView: true} + }; + case contextHandlerActionTypes.SINGLE_SUGGESTION_FOUND: + return { + ...state, + externalRequestFound: action.data + }; + case aaiActionTypes.SET_SECONDARY_TITLE: + return { + ...state, + secondaryTitle: action.data + }; } return state; }; diff --git a/src/app/contextHandler/ContextHandlerActions.js b/src/app/contextHandler/ContextHandlerActions.js new file mode 100644 index 0000000..3cd57f7 --- /dev/null +++ b/src/app/contextHandler/ContextHandlerActions.js @@ -0,0 +1,137 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import { + POST, + POST_HEADER +} from 'app/networking/NetworkConstants.js'; +import networkCall from 'app/networking/NetworkCalls.js'; +import {EXTERNAL_REQ_ENTITY_SEARCH_URL, +WRONG_EXTERNAL_REQUEST_MESSAGE, + WRONG_RESULT +} from 'app/contextHandler/ContextHandlerConstants'; +import { + getSetGlobalMessageEvent, + getClearGlobalMessageEvent +} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js'; + +import { STATUS_CODE_204_NO_CONTENT, + STATUS_CODE_3XX_REDIRECTION, + MESSAGE_LEVEL_DANGER +} from 'utils/GlobalConstants.js'; + + +import { + contextHandlerActionTypes +} from 'app/contextHandler/ContextHandlerConstants.js'; + +function getExternalParamValues(urlParams) { + var pairs = decodeURIComponent(urlParams).replace('?','').replace(/\r\n|\n/,'').split('&'); + + var externalparamObject = {}; + pairs.forEach(function(pair) { + pair = pair.split('='); + externalparamObject[pair[0]] = pair[1] || ''; + }); + return externalparamObject; + +} + +function validateExternalParams(externalURLParams) { + if(externalURLParams.view && externalURLParams.entityId && externalURLParams.entityType) { + return true; + } + return false; + +} + + +function createSuggestionFoundEvent(suggestion) { + return { + type: contextHandlerActionTypes.SINGLE_SUGGESTION_FOUND, + data: suggestion + }; +} + + +function fetchDataForExternalRequest(fetchRequestCallback) { + return dispatch => { + return fetchRequestCallback().then( + (response) => { + if (response.status === STATUS_CODE_204_NO_CONTENT || response.status >= STATUS_CODE_3XX_REDIRECTION) { + return Promise.reject(new Error(response.status)); + } else { + // assume 200 status + return response.json(); + } + } + ).then( + (results)=> { + if (results.suggestions !== undefined && results.suggestions.length === 1) { + dispatch(getClearGlobalMessageEvent()); + dispatch(createSuggestionFoundEvent({suggestion: results.suggestions[0]})); + } else { + dispatch(getSetGlobalMessageEvent(WRONG_RESULT , MESSAGE_LEVEL_DANGER)); + } + } + ).catch( + () => { + dispatch(getSetGlobalMessageEvent(WRONG_RESULT , MESSAGE_LEVEL_DANGER)); + } + ); + }; +} + +function validateAndFetchExternalParams(externalParams) { + if(!validateExternalParams(externalParams)) { + return dispatch => { + dispatch( + getSetGlobalMessageEvent(WRONG_EXTERNAL_REQUEST_MESSAGE, MESSAGE_LEVEL_DANGER)); + }; + } else { + let postBody = JSON.stringify(externalParams); + let externalfetchRequest = + () => networkCall.fetchRequestObj(EXTERNAL_REQ_ENTITY_SEARCH_URL, POST, + POST_HEADER, postBody); + return dispatch => { + dispatch(fetchDataForExternalRequest(externalfetchRequest)); + }; + } +} +export function externalUrlRequest(urlParams) { + let externalURLParams = getExternalParamValues(urlParams); + return dispatch => { + dispatch( + validateAndFetchExternalParams(externalURLParams)); + }; +} +export function externalMessageRequest(jsonParams) { + return dispatch => { + dispatch( + validateAndFetchExternalParams(jsonParams)); + }; + +} + diff --git a/src/app/contextHandler/ContextHandlerConstants.js b/src/app/contextHandler/ContextHandlerConstants.js new file mode 100644 index 0000000..4a0137f --- /dev/null +++ b/src/app/contextHandler/ContextHandlerConstants.js @@ -0,0 +1,41 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + + +import keyMirror from 'utils/KeyMirror.js'; +import {BASE_URL} from 'app/networking/NetworkConstants.js'; + +export const contextHandlerActionTypes = keyMirror({ + SINGLE_SUGGESTION_FOUND: null, + INVALID_SUGGESTION_FOUND: null +}); + +export const EXTERNAL_REQ_ENTITY_SEARCH_URL = BASE_URL + '/rest/search/externalRequestEntitySearch'; +export const WRONG_EXTERNAL_REQUEST_MESSAGE = 'External parameter request is incorrect'; +export const WRONG_RESULT = 'Invalid result for the requested external params.'; + + + + diff --git a/src/app/extensibility/ExtensibilityReducer.js b/src/app/extensibility/ExtensibilityReducer.js new file mode 100644 index 0000000..83f963a --- /dev/null +++ b/src/app/extensibility/ExtensibilityReducer.js @@ -0,0 +1,8 @@ +import {combineReducers} from 'redux'; + + +export default combineReducers({ + extensible: (state = {}) => { + return state; + } +}); diff --git a/src/app/extensibility/index.js b/src/app/extensibility/index.js new file mode 100644 index 0000000..49adff8 --- /dev/null +++ b/src/app/extensibility/index.js @@ -0,0 +1,7 @@ +// Import section (used as anchor to add extension imports) + +let components = {}; + +// Components section (used as an anchor to add extension components) + +export default components; diff --git a/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx index f29de3e..1410fd4 100644 --- a/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx +++ b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx @@ -1,30 +1,33 @@ /* - * ============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 {connect} from 'react-redux'; import React, {Component} from 'react'; import AutoCompleteSearchBar from 'generic-components/autoCompleteSearchBar/AutoCompleteSearchBar.jsx'; import {postAnalyticsData} from 'app/analytics/AnalyticsActions.js'; -import {getClearGlobalMessageEvent} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js'; +import {getClearGlobalMessageEvent} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js'; import { queryRequestedValues, clearSuggestionsTextField, diff --git a/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js index d04e7a1..d4ec356 100644 --- a/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js +++ b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js @@ -1,25 +1,28 @@ /* - * ============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 {getTSUIElasticSearchQueryString} from 'app/networking/NetworkUtil.js'; import networkCall from 'app/networking/NetworkCalls.js'; import { @@ -36,7 +39,7 @@ import { import { getSetGlobalMessageEvent, getClearGlobalMessageEvent -} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js'; +} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js'; function createSuggestionFoundEvent({suggestions}) { diff --git a/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js index 448466a..0fca9e8 100644 --- a/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js +++ b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js @@ -1,26 +1,29 @@ /* - * ============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 keyMirror from 'utils/KeyMirror.js'; import {BASE_URL} from 'app/networking/NetworkConstants.js'; @@ -36,7 +39,7 @@ export const globalAutoCompleteSearchBarActionTypes = keyMirror({ SEARCH_INVALID_TERMS: null }); -export const GLOBAL_SEARCH_URL = BASE_URL + '/search/querysearch/'; +export const GLOBAL_SEARCH_URL = BASE_URL + '/rest/search/querysearch/'; export const NO_MATCHES_FOUND = 'No Matches Found'; export const ERROR_INVALID_SEARCH_TERMS = 'Invalid search terms'; diff --git a/src/app/inventory/Inventory.jsx b/src/app/inventory/Inventory.jsx index b323446..106619f 100644 --- a/src/app/inventory/Inventory.jsx +++ b/src/app/inventory/Inventory.jsx @@ -1,25 +1,28 @@ /* - * ============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 Grid from 'react-bootstrap/lib/Grid'; @@ -46,7 +49,10 @@ import { import InlineMessage from 'generic-components/InlineMessage/InlineMessage.jsx'; import PaginatedTable from 'generic-components/paginatedTable/PaginatedTable.jsx'; import { - dateFormatLocalTimeZoneMMDDYYYY, getTicks, getTicksData, sortDataByField + dateFormatLocalTimeZoneYYYYMMDD, + getTicks, + getTicksData, + sortDataByField } from 'utils/DateTimeChartUtil.js'; import TitledContainer from 'generic-components/titledContainer/TitledContainer.jsx'; import {COLOR_BLUE} from 'utils/GlobalConstants.js'; @@ -114,7 +120,7 @@ class Inventory extends Component { let lastDate = ''; if (sortedData.length > 0) { lastDate = - dateFormatLocalTimeZoneMMDDYYYY(sortedData[sortedData.length - 1] + dateFormatLocalTimeZoneYYYYMMDD(sortedData[sortedData.length - 1] .date); totalEntities = sortedData[sortedData.length - 1].count; } @@ -159,12 +165,12 @@ class Inventory extends Component { }}> <XAxis dataKey={xAxisAttrName} ticks={ticksArr} tickCount={ticksArr.length} - tickFormatter={dateFormatLocalTimeZoneMMDDYYYY}/> + tickFormatter={dateFormatLocalTimeZoneYYYYMMDD}/> <YAxis/> <CartesianGrid strokeDasharray='3 3'/> - <Tooltip labelFormatter={dateFormatLocalTimeZoneMMDDYYYY}/> + <Tooltip labelFormatter={dateFormatLocalTimeZoneYYYYMMDD}/> <Brush dataKey={xAxisAttrName} - tickFormatter={dateFormatLocalTimeZoneMMDDYYYY} + tickFormatter={dateFormatLocalTimeZoneYYYYMMDD} height={20} stroke={COLOR_BLUE}/> <Line name={i18n(TOTAL_ENTITY_COUNTS_BY_DATE_CHART.yAxisLabel)} diff --git a/src/app/inventory/InventoryConstants.js b/src/app/inventory/InventoryConstants.js index c67fbba..9c289c2 100644 --- a/src/app/inventory/InventoryConstants.js +++ b/src/app/inventory/InventoryConstants.js @@ -1,25 +1,28 @@ /* - * ============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 keyMirror from 'utils/KeyMirror.js'; import {BASE_URL} from 'app/networking/NetworkConstants.js'; @@ -37,9 +40,9 @@ export const COMPLEX_BY_LOCATION_TITLE = 'Complexes By Location'; export const TOTAL_ENTITY_COUNT_TITLE = 'Total Entities'; export const ENTITIES_BY_TYPE_TITLE = 'Entities By Type'; -export const INVENTORY_COUNT_BY_TYPE_SEARCH_URL = BASE_URL + '/visualization/entityCountHistory?type=table'; -export const INVENTORY_COUNT_BY_DATE_SEARCH_URL = BASE_URL + '/visualization/entityCountHistory?type=graph'; -export const INVENTORY_GEO_VISUALIZATION_SEARCH_URL = BASE_URL + '/visualization/geovisualization'; +export const INVENTORY_COUNT_BY_TYPE_SEARCH_URL = BASE_URL + '/rest/visualization/entityCountHistory?type=table'; +export const INVENTORY_COUNT_BY_DATE_SEARCH_URL = BASE_URL + '/rest/visualization/entityCountHistory?type=graph'; +export const INVENTORY_GEO_VISUALIZATION_SEARCH_URL = BASE_URL + '/rest/visualization/geovisualization'; export const GEO_VISUALIZATION_QUERY_STRING_PARAMETERS = '/?entity='; export const TOTAL_ENTITY_COUNTS_BY_DATE_CHART = { diff --git a/src/app/main.app.jsx b/src/app/main.app.jsx index c92c11f..db86af9 100644 --- a/src/app/main.app.jsx +++ b/src/app/main.app.jsx @@ -1,29 +1,32 @@ /* - * ============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 'resources/scss/bootstrap.scss'; import 'resources/css/font-awesome.min.css'; import 'resources/css/react-datepicker.min.css'; -import 'resources/scss/style.scss'; +import 'resources/scss/customViews.scss'; import React from 'react'; import ReactDOM from 'react-dom'; @@ -31,6 +34,10 @@ import ReactDOM from 'react-dom'; import Application from './Application.jsx'; import MainScreenWrapper from './MainScreenWrapper.jsx'; +// Import Style Section +import 'resources/scss/style.scss'; + + ReactDOM.render( <Application><MainScreenWrapper /></Application>, document.getElementById('main-app')); diff --git a/src/app/networking/NetworkConstants.js b/src/app/networking/NetworkConstants.js index 9ff92c4..2ae5ef0 100644 --- a/src/app/networking/NetworkConstants.js +++ b/src/app/networking/NetworkConstants.js @@ -1,25 +1,28 @@ /* - * ============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. */ + export const POST = 'POST'; export const GET = 'GET'; export const POST_HEADER = {'Accept': 'application/json'}; @@ -28,8 +31,6 @@ export const BACKEND_POST_HEADER = { 'Accept': 'application/json', 'Content-Type': 'application/json' }; -export const AUDIT_SEARCH_DATE_FORMAT = 'YYYY-MM-DDTHH:mm:ss.SSSZ'; -export const AUDIT_SEARCH_DATE_TIME_ZONE = 'Z'; export const ERROR_RETRIEVING_DATA = 'Error fetching data from server'; export const NO_RESULTS_FOUND = 'No Results Found'; const BACKEND_IP_ADDRESS = document.location.hostname; diff --git a/src/app/networking/NetworkUtil.js b/src/app/networking/NetworkUtil.js index d3e772c..63f4eb6 100644 --- a/src/app/networking/NetworkUtil.js +++ b/src/app/networking/NetworkUtil.js @@ -1,47 +1,27 @@ /* - * ============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 { - AUDIT_SEARCH_DATE_FORMAT, - AUDIT_SEARCH_DATE_TIME_ZONE -} from './NetworkConstants.js'; - -export function getTableDateQueryString(requestObject) { - return { - 'queryParameters': { - 'startDate': requestObject.dateRange.startDate.format( - AUDIT_SEARCH_DATE_FORMAT), - 'endDate': requestObject.dateRange.endDate.format( - AUDIT_SEARCH_DATE_FORMAT), - 'time_zone': requestObject.dateRange.startDate.format( - AUDIT_SEARCH_DATE_TIME_ZONE), - 'typeData': { - 'type': 'pagination', - 'from': requestObject.startIndex, - 'size': requestObject.resultCount - } - } - }; -} export function getTSUIElasticSearchQueryString(query) { // Create the query request @@ -57,92 +37,3 @@ export function getTSUIElasticSearchQueryString(query) { 'queryStr': newQuery }; } -export function getSeverityVisualizationQueryString(requestObject) { - return { - 'queryParameters': { - 'startDate': requestObject.dateRange.startDate.format( - AUDIT_SEARCH_DATE_FORMAT), - 'endDate': requestObject.dateRange.endDate.format( - AUDIT_SEARCH_DATE_FORMAT), - 'time_zone': requestObject.dateRange.startDate.format( - AUDIT_SEARCH_DATE_TIME_ZONE), - 'typeData': { - 'type': 'groupBy', - 'groupByField': 'severity' - } - } - }; -} - -export function getStatusVisualizationQueryString(requestObject) { - return { - 'queryParameters': { - 'startDate': requestObject.dateRange.startDate.format( - AUDIT_SEARCH_DATE_FORMAT), - 'endDate': requestObject.dateRange.endDate.format( - AUDIT_SEARCH_DATE_FORMAT), - 'time_zone': requestObject.dateRange.startDate.format( - AUDIT_SEARCH_DATE_TIME_ZONE), - 'typeData': { - 'type': 'groupBy', - 'groupByField': 'category' - } - } - }; -} - -export function getEntityTypeVisualizationQueryString(requestObject) { - return { - 'queryParameters': { - 'startDate': requestObject.dateRange.startDate.format( - AUDIT_SEARCH_DATE_FORMAT), - 'endDate': requestObject.dateRange.endDate.format( - AUDIT_SEARCH_DATE_FORMAT), - 'time_zone': requestObject.dateRange.startDate.format( - AUDIT_SEARCH_DATE_TIME_ZONE), - 'typeData': { - 'type': 'groupBy', - 'groupByField': 'entityType' - } - } - }; -} - -export function getDateVisualizationQueryString(requestObject) { - return { - 'queryParameters': { - 'startDate': requestObject.dateRange.startDate.format( - AUDIT_SEARCH_DATE_FORMAT), - 'endDate': requestObject.dateRange.endDate.format( - AUDIT_SEARCH_DATE_FORMAT), - 'time_zone': requestObject.dateRange.startDate.format( - AUDIT_SEARCH_DATE_TIME_ZONE), - 'typeData': { - 'type': 'dateHistogram' - } - } - }; -} - -export function getVnfOrchStatusQueryString(requestObject) { - return { - 'hashId': requestObject, - 'groupby': 'orchestration-status' - }; -} -export function getVnfProvStatusQueryString(requestObject) { - return { - 'hashId': requestObject, - 'groupby': 'prov-status' - }; -} -export function getVnfCountQueryString(requestObject) { - return { - 'hashId': requestObject - }; -} - - - - - diff --git a/src/app/overlays/OverlayImports.js b/src/app/overlays/OverlayImports.js new file mode 100644 index 0000000..eabe9a5 --- /dev/null +++ b/src/app/overlays/OverlayImports.js @@ -0,0 +1,4 @@ +// Import section (used as anchor to add overlay imports) +let overlays = {}; +// Overlays section (used as an anchor to add overlay components) +export default overlays; diff --git a/src/app/tierSupport/TierSupport.jsx b/src/app/tierSupport/TierSupport.jsx index e6c479e..e38b43d 100644 --- a/src/app/tierSupport/TierSupport.jsx +++ b/src/app/tierSupport/TierSupport.jsx @@ -1,31 +1,40 @@ /* - * ============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 SplitPane from 'react-split-pane'; +import {setSecondaryTitle} from 'app/MainScreenWrapperActionHelper.js'; import ForceDirectedGraph from 'generic-components/graph/ForceDirectedGraph.jsx'; import SelectedNodeDetails from 'app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx'; + + +import overlaysDetails from 'resources/overlays/overlaysDetails.json'; +import * as Overlays from 'app/overlays/OverlayImports.js'; + import i18n from 'utils/i18n/i18n'; import { onNodeDetailsChange, @@ -39,7 +48,7 @@ import { TSUI_TITLE, TSUI_NODE_DETAILS_INITIAL_WIDTH, TSUI_NODE_DETAILS_MIN_WIDTH, - TSUI_GRAPH_MENU_NODE_DETAILS + TSUI_GRAPH_MENU_NODE_DETAILS, } from './TierSupportConstants.js'; let mapStateToProps = ( @@ -61,7 +70,8 @@ let mapStateToProps = ( windowHeight = 500, graphNodeSelectedMenu = TSUI_GRAPH_MENU_NODE_DETAILS, feedbackMsgText = '', - feedbackMsgSeverity = '' + feedbackMsgSeverity = '', + nodeData = {} } = tierSupportReducer; let { @@ -76,12 +86,16 @@ let mapStateToProps = ( performPrepareVisualization, selectedSuggestion, feedbackMsgText, - feedbackMsgSeverity + feedbackMsgSeverity, + nodeData }; }; let mapActionToProps = (dispatch) => { return { + onSetViewTitle: (title) => { + dispatch(setSecondaryTitle(title)); + }, onNodeSelected: (requestObject) => { dispatch(onNodeDetailsChange(requestObject)); }, @@ -110,7 +124,8 @@ class TierSupport extends Component { windowHeight: React.PropTypes.number, graphNodeSelectedMenu: React.PropTypes.string, feedbackMsgText: React.PropTypes.string, - feedbackMsgSeverity: React.PropTypes.string + feedbackMsgSeverity: React.PropTypes.string, + nodeData: React.PropTypes.object }; componentWillReceiveProps(nextProps) { @@ -119,6 +134,10 @@ class TierSupport extends Component { this.props.match.params.viParam) { this.props.onNewVIParam(nextProps.match.params.viParam); } + if(nextProps.match.params.viParam === undefined && nextProps.match.params.viParam !== + this.props.match.params.viParam) { + this.props.onRequestClearData(); + } if (nextProps.feedbackMsgText !== this.props.feedbackMsgText) { this.props.onMessageStateChange(nextProps.feedbackMsgText, @@ -127,6 +146,7 @@ class TierSupport extends Component { } componentWillMount() { + this.props.onSetViewTitle(i18n(TSUI_TITLE)); if (this.props.match.params.viParam) { this.props.onNewVIParam(this.props.match.params.viParam); } else { @@ -144,6 +164,7 @@ class TierSupport extends Component { } render() { + const { forceDirectedGraphRawData, onNodeSelected, @@ -152,17 +173,35 @@ class TierSupport extends Component { onSplitPaneResize, onNodeMenuSelect } = this.props; - let currentSelectedMenu = this.getCurrentSelectedMenu(); + + + let availableOverlay; + let overlayComponent; + // Currently only ONE overlay can be added to each view. + // todo: need to make it array if more than one overlay can be used. No need now. + overlaysDetails.forEach(function(overlay){ + if(overlay.view === 'schema') { + availableOverlay = overlay.key; + overlayComponent = overlay.componentName; + } + }); //Temp code for a demo, will be removed as Vis library is updated - let currentNodeButton = 'NODE_DETAILS'; + let currentNodeButton; + if(this.props.graphNodeSelectedMenu === + TSUI_GRAPH_MENU_NODE_DETAILS ) { + currentNodeButton = 'NODE_DETAILS'; + } else if(availableOverlay) { + currentNodeButton = availableOverlay; + } // End temp code - + let dataOverlayButtons = ['NODE_DETAILS']; + if(availableOverlay) { + dataOverlayButtons.push(availableOverlay); + } + let currentSelectedMenu = this.getCurrentSelectedMenu(overlayComponent); return ( <div className='tier-support-ui'> - <div className='secondary-header'> - <span className='secondary-title'>{i18n(TSUI_TITLE)}</span> - </div> <SplitPane split='vertical' enableResizing='true' @@ -184,7 +223,9 @@ class TierSupport extends Component { nodeButtonSelectedCallback={(selectedMenuId) => { onNodeMenuSelect(selectedMenuId); }} + dataOverlayButtons={dataOverlayButtons} currentlySelectedNodeView={currentNodeButton}/> + </div> <div> {currentSelectedMenu} @@ -194,15 +235,34 @@ class TierSupport extends Component { ); } - getCurrentSelectedMenu() { - switch (this.props.graphNodeSelectedMenu) { - case TSUI_GRAPH_MENU_NODE_DETAILS: - if (!this.nodeDetails) { - this.nodeDetails = <SelectedNodeDetails/>; + isNotEmpty(obj) { + for(var prop in obj) { + if(obj.hasOwnProperty(prop)) { + return true; + } + } + return false; + } + + getCurrentSelectedMenu(overlayComponent) { + let secondOverlay; + if (this.props.graphNodeSelectedMenu === TSUI_GRAPH_MENU_NODE_DETAILS) { + if (!this.nodeDetails) { + this.nodeDetails = <SelectedNodeDetails/>; + } + return this.nodeDetails; + } + else { + if (this.isNotEmpty(this.props.nodeData) && overlayComponent) { + if (Overlays.default.hasOwnProperty(overlayComponent)) { + let OverlayComponent = Overlays.default[overlayComponent]; + secondOverlay = <OverlayComponent nodeDetails={this.props.nodeData}/>; } - return this.nodeDetails; + } + return secondOverlay; } } + } export default connect(mapStateToProps, mapActionToProps)(TierSupport); diff --git a/src/app/tierSupport/TierSupportActions.js b/src/app/tierSupport/TierSupportActions.js index 4261360..6de6ab0 100644 --- a/src/app/tierSupport/TierSupportActions.js +++ b/src/app/tierSupport/TierSupportActions.js @@ -1,26 +1,29 @@ /* - * ============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 {tierSupportActionTypes, TS_BACKEND_SEARCH_SELECTED_NODE_URL} from 'app/tierSupport/TierSupportConstants.js'; import { @@ -33,7 +36,7 @@ import networkCall from 'app/networking/NetworkCalls.js'; import { getSetGlobalMessageEvent, getClearGlobalMessageEvent -} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js'; +} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js'; import { STATUS_CODE_204_NO_CONTENT, STATUS_CODE_3XX_REDIRECTION, @@ -86,6 +89,20 @@ function createNodeDetailsFoundEvent(nodeDetails) { }; } +function createSelectedNodeDetails(nodeDetails) { + var selectedNodeDetail; + for(let i = 0; i < nodeDetails.nodes.length; i++) { + if(nodeDetails.nodes[i].nodeMeta.className === 'selectedSearchedNodeClass') { + selectedNodeDetail = nodeDetails.nodes[i]; + break; + } + } + return { + type: tierSupportActionTypes.TS_GRAPH_NODE_SELECTED, + data: selectedNodeDetail + }; +} + function noNodeDetailsFoundEvent(errorText) { return { type: tierSupportActionTypes.TS_NODE_SEARCH_NO_RESULTS, @@ -121,6 +138,7 @@ export function fetchSelectedNodeElement(fetchRequestCallback) { (responseJson) => { if (responseJson.nodes.length > 0) { dispatch(createNodeDetailsFoundEvent(responseJson)); + dispatch(createSelectedNodeDetails(responseJson)); } else { dispatch(noNodeDetailsFoundEvent(NO_RESULTS_FOUND)); } diff --git a/src/app/tierSupport/TierSupportConstants.js b/src/app/tierSupport/TierSupportConstants.js index 9383d65..1a525b1 100644 --- a/src/app/tierSupport/TierSupportConstants.js +++ b/src/app/tierSupport/TierSupportConstants.js @@ -1,25 +1,28 @@ /* - * ============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 keyMirror from 'utils/KeyMirror.js'; import {BASE_URL} from 'app/networking/NetworkConstants.js'; @@ -37,10 +40,10 @@ export const tierSupportActionTypes = keyMirror({ export const TSUI_NODE_DETAILS_INITIAL_WIDTH = 300; export const TSUI_NODE_DETAILS_MIN_WIDTH = 200; -export const TSUI_SEARCH_URL = BASE_URL + '/search/viuiSearch/'; +export const TSUI_SEARCH_URL = BASE_URL + '/rest/search/viuiSearch/'; export const TSUI_TITLE = 'View & Inspect'; export const TSUI_GRAPH_MENU_NODE_DETAILS = 'NODE_DETAILS'; -export const SEARCH_SELECTED_NODE_PATH = '/visualization/prepareVisualization'; +export const SEARCH_SELECTED_NODE_PATH = '/rest/visualization/prepareVisualization'; export const TS_BACKEND_SEARCH_SELECTED_NODE_URL = BASE_URL + SEARCH_SELECTED_NODE_PATH; diff --git a/src/app/tierSupport/TierSupportReducer.js b/src/app/tierSupport/TierSupportReducer.js index 3c4e83e..7dd6ab0 100644 --- a/src/app/tierSupport/TierSupportReducer.js +++ b/src/app/tierSupport/TierSupportReducer.js @@ -1,25 +1,28 @@ /* - * ============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 {combineReducers} from 'redux'; import ForceDirectedGraph from 'generic-components/graph/ForceDirectedGraph.jsx'; import {aaiActionTypes} from 'app/MainScreenWrapperConstants.js'; @@ -43,7 +46,7 @@ export default combineReducers({ case tierSupportActionTypes.TS_NODE_SEARCH_RESULTS: let graphData = ForceDirectedGraph.generateNewProps(action.data.nodes, action.data.links, action.data.graphMeta); - + return { ...state, forceDirectedGraphRawData: graphData, @@ -81,6 +84,11 @@ export default combineReducers({ feedbackMsgText: '', feedbackMsgSeverity: '' }; + case tierSupportActionTypes.TS_GRAPH_NODE_SELECTED: + return { + ...state, + nodeData: action.data + }; case globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT: let emptyNodesAndLinksWarningEvent = ForceDirectedGraph.generateNewProps([], [], {}); return { @@ -93,7 +101,7 @@ export default combineReducers({ let splitPaneLeftSideElement = document.getElementsByClassName('Pane1'); if (splitPaneLeftSideElement.length > 0) { let width = splitPaneLeftSideElement[0].offsetWidth; - + return { ...state, windowWidth: width, windowHeight: splitPaneLeftSideElement[0].offsetHeight }; @@ -101,7 +109,7 @@ export default combineReducers({ return state; } } - + return state; } }); diff --git a/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx index 97fa4ec..267a1c3 100644 --- a/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx +++ b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx @@ -1,25 +1,28 @@ /* - * ============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 {connect} from 'react-redux'; import React, {Component} from 'react'; import Table from 'react-bootstrap/lib/Table'; @@ -31,7 +34,7 @@ import { } from 'app/tierSupport/selectedNodeDetails/SelectedNodeDetailsConstants.js'; let mapStateToProps = ({tierSupport: {selectedNodeDetails}}) => { - let {nodeData = [], nodeType = '', uid = ''} = selectedNodeDetails; + let {nodeData = {}, nodeType = '', uid = ''} = selectedNodeDetails; return { nodeData, @@ -42,7 +45,7 @@ let mapStateToProps = ({tierSupport: {selectedNodeDetails}}) => { class SelectedNodeDetails extends Component { static propTypes = { - nodeData: React.PropTypes.array, + nodeData: React.PropTypes.object, nodeType: React.PropTypes.string, uid: React.PropTypes.string }; 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 ( + <VerticalFilterBar + filtersConfig={this.props.vnfFilters} + filterValues={this.props.unifiedFilterValues} + filterTitle={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> ); } diff --git a/src/app/vnfSearch/VnfSearchActions.js b/src/app/vnfSearch/VnfSearchActions.js index b28ab66..ce09b2a 100644 --- a/src/app/vnfSearch/VnfSearchActions.js +++ b/src/app/vnfSearch/VnfSearchActions.js @@ -1,35 +1,38 @@ /* - * ============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 { vnfActionTypes, - VNF_RESULT_URL + VNF_FILTER_AGGREGATION_URL, + CHART_PROV_STATUS, + CHART_ORCH_STATUS, + CHART_NF_TYPE, + CHART_NF_ROLE, + TOTAL_VNF_COUNT, + VNF_FILTER_EMPTY_RESULT } from 'app/vnfSearch/VnfSearchConstants.js'; - -import { - getVnfProvStatusQueryString, - getVnfOrchStatusQueryString, - getVnfCountQueryString -} from 'app/networking/NetworkUtil.js'; import { POST, POST_HEADER, @@ -38,7 +41,8 @@ import { import { getSetGlobalMessageEvent, getClearGlobalMessageEvent -} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js'; +} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js'; +import {MESSAGE_LEVEL_WARNING} from 'utils/GlobalConstants.js'; let fetch = require('node-fetch'); fetch.Promise = require('es6-promise').Promise; @@ -52,143 +56,174 @@ function getInvalidQueryEvent() { data: {errorMsg: ERROR_RETRIEVING_DATA} }; } -/*it is a vertical bar chart then y and x are switched */ -function getProvStatusEvent(responseJson) { - if (responseJson && responseJson.groupby_aggregation && - responseJson.groupby_aggregation.buckets && - responseJson.groupby_aggregation.buckets.length > 0) { - let groupByProvStatusBucket; - let dataPoints = []; - for (groupByProvStatusBucket of - responseJson.groupby_aggregation.buckets) { - dataPoints.push({ - 'x': groupByProvStatusBucket[itemKeyWord].split('=', 1)[0], - 'y': groupByProvStatusBucket[countKeyWord] - }); - } - let newProvStatusChartData = [ +function processProvData(provDataList) { + let dataPoints = []; + let newProvStatusChartData = CHART_PROV_STATUS.emptyData; + for (let provData of provDataList) { + dataPoints.push( { - 'values': dataPoints + 'x': provData[itemKeyWord], + 'y': provData[countKeyWord] } - ]; - - let provStatusCountChartData = { - chartData: newProvStatusChartData - }; - return { - type: vnfActionTypes.COUNT_BY_PROV_STATUS_RECEIVED, - data: {provStatusCountChartData} - }; + ); } - else { - return { - type: vnfActionTypes.ERROR_NO_DATA_FOR_PROV_STATUS_IN_SEARCH_RANGE_RECEIVED + + if (dataPoints.length > 0) { + newProvStatusChartData = { + 'values': dataPoints }; } -} -function getOrchStatusEvent(responseJson) { - if (responseJson && responseJson.groupby_aggregation && - responseJson.groupby_aggregation.buckets && - responseJson.groupby_aggregation.buckets.length > 0) { - let groupByOrchStatusBucket; - let dataPoints = []; - for (groupByOrchStatusBucket of - responseJson.groupby_aggregation.buckets) { - dataPoints.push({ - 'x': groupByOrchStatusBucket[itemKeyWord].split('=', 1)[0], - 'y': groupByOrchStatusBucket[countKeyWord] - }); - } + return newProvStatusChartData; +} - let newOrchStatusChartData = [ +function processOrchData(orchDataList) { + let dataPoints = []; + let newOrchStatusChartData = CHART_ORCH_STATUS.emptyData; + for (let orchData of orchDataList) { + dataPoints.push( { - 'values': dataPoints + 'x': orchData[itemKeyWord], + 'y': orchData[countKeyWord] } - ]; - - let orchStatusCountChartData = { - chartData: newOrchStatusChartData - }; - return { - type: vnfActionTypes.COUNT_BY_ORCH_STATUS_RECEIVED, - data: {orchStatusCountChartData} - }; + ); } - else { - return { - type: vnfActionTypes.ERROR_NO_DATA_FOR_ORCH_STATUS_IN_SEARCH_RANGE_RECEIVED + + if (dataPoints.length > 0) { + newOrchStatusChartData = { + 'values': dataPoints }; } + + return newOrchStatusChartData; } -function getTotalVnfEvent(responseJson) { - if (responseJson && responseJson.count && responseJson.count > 0) { - return { - type: vnfActionTypes.TOTAL_VNF_COUNT_RECEIVED, - data: {count: responseJson.count} - }; +function processNfTypeData(nfDataList) { + let dataPoints = []; + let newNfTypeChartData = CHART_NF_TYPE.emptyData; + for (let nfData of nfDataList) { + dataPoints.push( + { + 'x': nfData[itemKeyWord], + 'y': nfData[countKeyWord] + } + ); } - else { - return { - type: vnfActionTypes.ERROR_NO_COUNT_RECEIVED + + if (dataPoints.length > 0) { + newNfTypeChartData = { + 'values': dataPoints }; } + + return newNfTypeChartData; } -export function processProvStatusVisualizationOnSearchChange(requestObject) { - return dispatch => { - return fetch(VNF_RESULT_URL, { - method: POST, - headers: POST_HEADER, - body: JSON.stringify(getVnfProvStatusQueryString(requestObject)) - }).then( - (response) => response.json() - ).then( - (responseJson) => { - dispatch(getProvStatusEvent(responseJson)); - } - ).catch( - () => { - dispatch(getInvalidQueryEvent()); +function processNfRoleData(nfDataList) { + let dataPoints = []; + let newNfRoleChartData = CHART_NF_ROLE.emptyData; + for (let nfData of nfDataList) { + dataPoints.push( + { + 'x': nfData[itemKeyWord], + 'y': nfData[countKeyWord] } ); + } + + if (dataPoints.length > 0) { + newNfRoleChartData = { + 'values': dataPoints + }; + } + + return newNfRoleChartData; +} + +function getVnfFilterAggregationQueryString(filterValueMap) { + let filterList = []; + + for (let filter in filterValueMap) { + if (filterValueMap[filter] !== '') { + filterList.push( + { + 'filterId': filter, + 'filterValue': filterValueMap[filter] + } + ); + } else { + filterList.push( + { + 'filterId': filter + } + ); + } + } + + return { + 'filters': filterList }; } -export function processOrchStatusVisualizationOnSearchChange(requestObject) { - return dispatch => { - return fetch(VNF_RESULT_URL, { - method: POST, - headers: POST_HEADER, - body: JSON.stringify(getVnfOrchStatusQueryString(requestObject)) - }).then( - (response) => response.json() - ).then( - (responseJson) => { - dispatch(getOrchStatusEvent(responseJson)); - } - ).catch( - () => { - dispatch(getInvalidQueryEvent()); - } - ); +function getVnfVisualizationsResultsEvent(results) { + let count = TOTAL_VNF_COUNT.emptyData; + let provData = CHART_PROV_STATUS.emptyData; + let orchData = CHART_ORCH_STATUS.emptyData; + let netFuncTypeData = CHART_NF_TYPE.emptyData; + let netFuncRoleData = CHART_NF_ROLE.emptyData; + + if (results.total) { + count = results.total; + } + + if (results['aggregations'] && results['aggregations']['prov-status']) { + provData = processProvData(results['aggregations']['prov-status']); + } + + if (results['aggregations'] && + results['aggregations']['orchestration-status']) { + orchData = processOrchData(results['aggregations']['orchestration-status']); + } + + if (results['aggregations'] && + results['aggregations']['nf-type']) { + netFuncTypeData = processNfTypeData(results['aggregations']['nf-type']); + } + + if (results['aggregations'] && + results['aggregations']['nf-role']) { + netFuncRoleData = processNfRoleData(results['aggregations']['nf-role']); + } + + return { + type: vnfActionTypes.VNF_SEARCH_RESULTS_RECEIVED, + data: { + count: count, + provStatusData: provData, + orchStatusData: orchData, + nfTypeData: netFuncTypeData, + nfRoleData: netFuncRoleData + } }; } -export function processTotalVnfVisualizationOnSearchChange(requestObject) { +export function processVnfVisualizationsOnFilterChange(filterValueMap) { return dispatch => { - return fetch(VNF_RESULT_URL + '/count', { + return fetch(VNF_FILTER_AGGREGATION_URL, { method: POST, headers: POST_HEADER, - body: JSON.stringify( - getVnfCountQueryString(requestObject)) + body: JSON.stringify(getVnfFilterAggregationQueryString(filterValueMap)) }).then( (response) => response.json() ).then( (responseJson) => { - dispatch(getTotalVnfEvent(responseJson)); + if(responseJson.total === 0) { + dispatch(getSetGlobalMessageEvent(VNF_FILTER_EMPTY_RESULT, MESSAGE_LEVEL_WARNING)); + } else { + dispatch(getClearGlobalMessageEvent()); + } + dispatch(getVnfVisualizationsResultsEvent(responseJson)); } ).catch( () => { @@ -198,6 +233,21 @@ export function processTotalVnfVisualizationOnSearchChange(requestObject) { }; } +export function processVnfFilterPanelCollapse(isOpen) { + let vnfVisualizationPanelClass = 'collapsible-panel-main-panel'; + + if (isOpen) { + vnfVisualizationPanelClass += ' vertical-filter-panel-is-open'; + } + + return { + type: vnfActionTypes.VNF_FILTER_PANEL_TOGGLED, + data: { + vnfVisualizationPanelClass: vnfVisualizationPanelClass + } + }; +} + export function setNotificationText(msgText, msgSeverity) { if (msgText.length > 0) { return dispatch => { @@ -210,3 +260,16 @@ export function setNotificationText(msgText, msgSeverity) { }; } } + +export function clearVnfSearchData() { + return { + type: vnfActionTypes.VNF_SEARCH_RESULTS_RECEIVED, + data: { + count: '', + provStatusData: CHART_PROV_STATUS.emptyData, + orchStatusData: CHART_ORCH_STATUS.emptyData, + nfTypeData: CHART_NF_TYPE.emptyData, + nfRoleData: CHART_NF_ROLE.emptyData + } + }; +} diff --git a/src/app/vnfSearch/VnfSearchConstants.js b/src/app/vnfSearch/VnfSearchConstants.js index 5f920fd..604c96f 100644 --- a/src/app/vnfSearch/VnfSearchConstants.js +++ b/src/app/vnfSearch/VnfSearchConstants.js @@ -1,69 +1,92 @@ /* - * ============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 keyMirror from 'utils/KeyMirror.js'; import {BASE_URL} from 'app/networking/NetworkConstants.js'; export const VNF_TITLE = 'VNFs'; +export const VNF_SEARCH_FILTER_NAME = 'vnfSearch'; export const vnfActionTypes = keyMirror({ - COUNT_BY_PROV_STATUS_RECEIVED: null, - ERROR_NO_DATA_FOR_PROV_STATUS_IN_SEARCH_RANGE_RECEIVED: null, - COUNT_BY_ORCH_STATUS_RECEIVED: null, - ERROR_NO_DATA_FOR_ORCH_STATUS_IN_SEARCH_RANGE_RECEIVED: null, - TOTAL_VNF_COUNT_RECEIVED: null, - ERROR_NO_COUNT_RECEIVED: null, - VNF_NETWORK_ERROR: null + VNF_NETWORK_ERROR: null, + VNF_SEARCH_RESULTS_RECEIVED: null, + VNF_SEARCH_FILTERS_RECEIVED: null, + VNF_FILTER_PANEL_TOGGLED: null }); export const CHART_PROV_STATUS = { title: 'VNFs By Provisioning Status', yAxisLabel: 'VNFs', xAxisLabel: 'VNFs', - emptyData: [{'values': [ + emptyData: {'values': [ { 'x': 'No data discovered for Provisioning Status', 'y': 0 } - ]}] + ]} }; export const CHART_ORCH_STATUS = { title: 'VNFs By Orchestration Status', yAxisLabel: 'VNFs', - emptyData: [{'values': [ + emptyData: {'values': [ { 'x': 'No data discovered for Orchestration Status', 'y': 0 } - ]}] + ]} +}; + +export const CHART_NF_TYPE = { + title: 'VNFs By Network Function Type', + yAxisLabel: 'VNFs', + emptyData: {'values': [ + { + 'x': 'No data discovered for Network Function Type', + 'y': 0 + } + ]} +}; + +export const CHART_NF_ROLE = { + title: 'VNFs By Network Function Role', + yAxisLabel: 'VNFs', + emptyData: {'values': [ + { + 'x': 'No data discovered for Network Function Role', + 'y': 0 + } + ]} }; export const TOTAL_VNF_COUNT = { title: 'Total VNFs', - emptyValue: 0 + emptyValue: '' }; -export const VNF_RESULT_URL = BASE_URL + '/search/summarybyentitytype'; +export const VNF_FILTER_AGGREGATION_URL = BASE_URL + '/rest/search/filterAggregation'; export const DEFAULT_VNFS_SEARCH_HASH = '2172a3c25ae56e4995038ffbc1f055692bfc76c0b8ceda1205bc745a9f7a805d'; export const VNFS_ROUTE = 'vnfSearch'; +export const VNF_FILTER_EMPTY_RESULT = 'No data for the specified filters'; diff --git a/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx b/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx new file mode 100644 index 0000000..ee8dd4f --- /dev/null +++ b/src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx @@ -0,0 +1,98 @@ +/* eslint-disable max-len,max-len,max-len,max-len,max-len,max-len */ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import React, {Component} from 'react'; +import {connect} from 'react-redux'; +import { + BarChart, + Bar, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + ResponsiveContainer, +} from 'recharts'; + +import i18n from 'utils/i18n/i18n'; + +import {CHART_NF_ROLE} from 'app/vnfSearch/VnfSearchConstants.js'; +import {COLOR_BLUE} from 'utils/GlobalConstants.js'; + +let mapStateToProps = ({vnfSearch}) => { + let { + processedNfRoleCountChartData = CHART_NF_ROLE.emptyData + } = vnfSearch; + + return { + processedNfRoleCountChartData + }; +}; + +class VnfSearchNfRoleVisualization extends Component { + static propTypes = { + processedNfRoleCountChartData: React.PropTypes.object + }; + + render() { + let { + processedNfRoleCountChartData + } = this.props; + + let visualizationClass = 'visualizations'; + + if (processedNfRoleCountChartData.values === + null || + processedNfRoleCountChartData.values.size <= + 0) { + visualizationClass = 'visualizations hidden'; + } + + const xAxisAttrName = 'x'; + const yAxisAttrName = 'y'; + + return ( + <div id='audit-visualizations' className={visualizationClass}> + <div className='visualization-charts'> + <div> + <h3>{i18n(CHART_NF_ROLE.title)}</h3> + <ResponsiveContainer width='100%' height={300}> + <BarChart data={processedNfRoleCountChartData.values}> + <XAxis dataKey={xAxisAttrName}/> + <YAxis/> + <CartesianGrid strokeDasharray='3 3'/> + <Tooltip/> + <Bar name={i18n(CHART_NF_ROLE.yAxisLabel)} + dataKey={yAxisAttrName} fill={COLOR_BLUE}/> + </BarChart> + </ResponsiveContainer> + </div> + </div> + </div> + ); + } +} + +export default connect(mapStateToProps)(VnfSearchNfRoleVisualization); diff --git a/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx b/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx new file mode 100644 index 0000000..292a68a --- /dev/null +++ b/src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx @@ -0,0 +1,96 @@ +/* eslint-disable max-len,max-len,max-len,max-len,max-len,max-len */ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import React, {Component} from 'react'; +import {connect} from 'react-redux'; +import { + BarChart, + Bar, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + ResponsiveContainer, +} from 'recharts'; + +import i18n from 'utils/i18n/i18n'; + +import {CHART_NF_TYPE} from 'app/vnfSearch/VnfSearchConstants.js'; +import {COLOR_BLUE} from 'utils/GlobalConstants.js'; + +let mapStateToProps = ({vnfSearch}) => { + let { + processedNfTypeCountChartData = CHART_NF_TYPE.emptyData + } = vnfSearch; + + return { + processedNfTypeCountChartData + }; +}; + +class VnfSearchNfTypeVisualization extends Component { + static propTypes = { + processedNfTypeCountChartData: React.PropTypes.object + }; + + render() { + let { + processedNfTypeCountChartData + } = this.props; + + let visualizationClass = 'visualizations'; + if (processedNfTypeCountChartData.values === + null || + processedNfTypeCountChartData.values.size <= + 0) { + visualizationClass = 'visualizations hidden'; + } + const xAxisAttrName = 'x'; + const yAxisAttrName = 'y'; + + return ( + <div id='audit-visualizations' className={visualizationClass}> + <div className='visualization-charts'> + <div > + <h3>{i18n(CHART_NF_TYPE.title)}</h3> + <ResponsiveContainer width='100%' height={300}> + <BarChart data={processedNfTypeCountChartData.values}> + <XAxis dataKey={xAxisAttrName}/> + <YAxis /> + <CartesianGrid strokeDasharray='3 3'/> + <Tooltip/> + <Bar name={i18n(CHART_NF_TYPE.yAxisLabel)} + dataKey={yAxisAttrName} fill={COLOR_BLUE}/> + </BarChart> + </ResponsiveContainer> + </div> + </div> + </div> + ); + } + +} +export default connect(mapStateToProps)(VnfSearchNfTypeVisualization); diff --git a/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx b/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx index 7e101b3..59f43eb 100644 --- a/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx @@ -1,26 +1,28 @@ +/* eslint-disable max-len,max-len,max-len,max-len,max-len,max-len */ /* - * ============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. */ -/* eslint-disable max-len,max-len,max-len,max-len,max-len,max-len */ import React, {Component} from 'react'; import {connect} from 'react-redux'; @@ -58,9 +60,9 @@ class VnfSearchOrchStatusVisualizations extends Component { } = this.props; let visualizationClass = 'visualizations'; - if (processedOrchStatusCountChartData[0].values === + if (processedOrchStatusCountChartData.values === null || - processedOrchStatusCountChartData[0].values.size <= + processedOrchStatusCountChartData.values.size <= 0) { visualizationClass = 'visualizations hidden'; } @@ -73,7 +75,7 @@ class VnfSearchOrchStatusVisualizations extends Component { <div > <h3>{i18n(CHART_ORCH_STATUS.title)}</h3> <ResponsiveContainer width='100%' height={300}> - <BarChart data={processedOrchStatusCountChartData[0].values}> + <BarChart data={processedOrchStatusCountChartData.values}> <XAxis dataKey={xAxisAttrName}/> <YAxis /> <CartesianGrid strokeDasharray='3 3'/> diff --git a/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx b/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx index d889d20..5295e35 100644 --- a/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx @@ -1,26 +1,28 @@ +/* eslint-disable max-len,max-len,max-len,max-len,max-len,max-len */ /* - * ============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. */ -/* eslint-disable max-len,max-len,max-len,max-len,max-len,max-len */ import React, {Component} from 'react'; import {connect} from 'react-redux'; @@ -51,7 +53,7 @@ let mapStateToProps = ({vnfSearch}) => { class VnfSearchProvStatusVisualization extends Component { static propTypes = { - processedProvStatusCountChartData: React.PropTypes.array + processedProvStatusCountChartData: React.PropTypes.object }; render() { @@ -60,9 +62,9 @@ class VnfSearchProvStatusVisualization extends Component { } = this.props; let visualizationClass = 'visualizations'; - if (processedProvStatusCountChartData[0].values === + if (processedProvStatusCountChartData.values === null || - processedProvStatusCountChartData[0].values.size <= + processedProvStatusCountChartData.values.size <= 0) { visualizationClass = 'visualizations hidden'; } @@ -76,7 +78,7 @@ class VnfSearchProvStatusVisualization extends Component { <h3>{i18n(CHART_PROV_STATUS.title)}</h3> <ResponsiveContainer width='100%' height={300}> <BarChart - data={processedProvStatusCountChartData[0].values}> + data={processedProvStatusCountChartData.values}> <XAxis dataKey={xAxisAttrName}/> <YAxis /> <CartesianGrid strokeDasharray='3 3'/> diff --git a/src/app/vnfSearch/VnfSearchReducer.js b/src/app/vnfSearch/VnfSearchReducer.js index 6dfc412..4c8337f 100644 --- a/src/app/vnfSearch/VnfSearchReducer.js +++ b/src/app/vnfSearch/VnfSearchReducer.js @@ -1,29 +1,33 @@ /* - * ============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 {vnfActionTypes} from 'app/vnfSearch/VnfSearchConstants.js'; import { CHART_ORCH_STATUS, CHART_PROV_STATUS, + CHART_NF_ROLE, + CHART_NF_TYPE, TOTAL_VNF_COUNT } from 'app/vnfSearch/VnfSearchConstants.js'; import {ERROR_RETRIEVING_DATA} from 'app/networking/NetworkConstants.js'; @@ -31,63 +35,85 @@ import {MESSAGE_LEVEL_DANGER} from 'utils/GlobalConstants.js'; import { globalAutoCompleteSearchBarActionTypes } from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js'; +import { + filterBarActionTypes +} from 'generic-components/filterBar/FilterBarConstants.js'; export default (state = {}, action) => { let data = action.data; switch (action.type) { - - case vnfActionTypes.COUNT_BY_PROV_STATUS_RECEIVED: + case vnfActionTypes.VNF_NETWORK_ERROR: return { ...state, - processedProvStatusCountChartData: data.provStatusCountChartData.chartData, - feedbackMsgText: '', - feedbackMsgSeverity: '' + processedProvStatusCountChartData: CHART_PROV_STATUS.emptyData, + processedOrchStatusCountChartData: CHART_ORCH_STATUS.emptyData, + processedNfTypeCountChartData: CHART_NF_TYPE.emptyData, + processedNfRoleCountChartData: CHART_NF_ROLE.emptyData, + count: TOTAL_VNF_COUNT.emptyValue, + feedbackMsgText: ERROR_RETRIEVING_DATA, + feedbackMsgSeverity: MESSAGE_LEVEL_DANGER }; - - case vnfActionTypes.COUNT_BY_ORCH_STATUS_RECEIVED: + case globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT: return { ...state, - processedOrchStatusCountChartData: data.orchStatusCountChartData.chartData, - feedbackMsgText: '', - feedbackMsgSeverity: '' + processedProvStatusCountChartData: CHART_PROV_STATUS.emptyData, + processedOrchStatusCountChartData: CHART_ORCH_STATUS.emptyData, + processedNfTypeCountChartData: CHART_NF_TYPE.emptyData, + processedNfRoleCountChartData: CHART_NF_ROLE.emptyData, + count: TOTAL_VNF_COUNT.emptyValue + }; + case filterBarActionTypes.NEW_SELECTIONS: + return { + ...state, + vnfFilterValues: data.selectedValuesMap, + unifiedFilterValues: data.unifiedValues + }; + case filterBarActionTypes.SET_UNIFIED_VALUES: + return { + ...state, + unifiedFilterValues: data }; - case vnfActionTypes.TOTAL_VNF_COUNT_RECEIVED: + case vnfActionTypes.VNF_SEARCH_RESULTS_RECEIVED: return { ...state, count: data.count, + processedProvStatusCountChartData: data.provStatusData, + processedOrchStatusCountChartData: data.orchStatusData, + processedNfTypeCountChartData: data.nfTypeData, + processedNfRoleCountChartData: data.nfRoleData, feedbackMsgText: '', feedbackMsgSeverity: '' }; - case vnfActionTypes.ERROR_NO_DATA_FOR_PROV_STATUS_IN_SEARCH_RANGE_RECEIVED: + case vnfActionTypes.VNF_FILTER_PANEL_TOGGLED: return { ...state, - processedProvStatusCountChartData: CHART_PROV_STATUS.emptyData, + vnfVisualizationPanelClass: data.vnfVisualizationPanelClass }; - case vnfActionTypes.ERROR_NO_DATA_FOR_ORCH_STATUS_IN_SEARCH_RANGE_RECEIVED: + case vnfActionTypes.VNF_SEARCH_FILTERS_RECEIVED: return { ...state, - processedOrchStatusCountChartData: CHART_ORCH_STATUS.emptyData, + vnfFilters: data }; - case vnfActionTypes.ERROR_NO_COUNT_RECEIVED: + case filterBarActionTypes.SET_NON_CONVERTED_VALUES: return { ...state, - count: TOTAL_VNF_COUNT.emptyValue, + nonConvertedFilters: data }; - case vnfActionTypes.VNF_NETWORK_ERROR: + case filterBarActionTypes.SET_CONVERTED_VALUES: return { ...state, - processedProvStatusCountChartData: CHART_PROV_STATUS.emptyData, - processedOrchStatusCountChartData: CHART_ORCH_STATUS.emptyData, - count: TOTAL_VNF_COUNT.emptyValue, - feedbackMsgText: ERROR_RETRIEVING_DATA, - feedbackMsgSeverity: MESSAGE_LEVEL_DANGER + nonConvertedFilters: {}, + unifiedFilterValues: data.convertedValues, + vnfFilterValues: data.nonConvertedValues // launching DI view via menu button requires this + // to be set so visualizations and table will populate themselves }; - case globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT: + case filterBarActionTypes.CLEAR_FILTERS: return { ...state, - processedProvStatusCountChartData: CHART_PROV_STATUS.emptyData, - processedOrchStatusCountChartData: CHART_ORCH_STATUS.emptyData, - count: TOTAL_VNF_COUNT.emptyValue + vnfFilters: {}, + vnfFilterValues: {}, + nonConvertedFilters: {}, + unifiedFilterValues: {} }; } diff --git a/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx b/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx index 690b5ee..5d3f1f2 100644 --- a/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx +++ b/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx @@ -1,26 +1,28 @@ +/* eslint-disable max-len,max-len,max-len,max-len,max-len,max-len */ /* - * ============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. */ -/* eslint-disable max-len,max-len,max-len,max-len,max-len,max-len */ import React, {Component} from 'react'; import {connect} from 'react-redux'; @@ -41,7 +43,10 @@ let mapStateToProps = ({vnfSearch}) => { class VnfSearchTotalCountVisualization extends Component { static propTypes = { - count: React.PropTypes.number + count: React.PropTypes.oneOfType([ + React.PropTypes.string, + React.PropTypes.number + ]) }; render() { diff --git a/src/editAttributes/AppStore.js b/src/editAttributes/AppStore.js new file mode 100644 index 0000000..cc626a0 --- /dev/null +++ b/src/editAttributes/AppStore.js @@ -0,0 +1,56 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import {combineReducers, createStore, compose, applyMiddleware} from 'redux'; +import thunkMiddleware from 'redux-thunk'; +import {reducer as formReducer} from 'redux-form'; + +import SetAttributeReducer from './EditAttributeReducer.js'; + +function createCompose() { + if (window.devToolsExtension) { + return compose( + applyMiddleware(thunkMiddleware), + window.devToolsExtension()); + } + else { + return applyMiddleware(thunkMiddleware); + } +} + +export const storeCreator = (initialState) => createStore( + combineReducers({ + setAttributes: SetAttributeReducer, + form: formReducer + }), + initialState, + createCompose() +); + + +const store = storeCreator(); + +export default store; + diff --git a/src/editAttributes/Application.jsx b/src/editAttributes/Application.jsx new file mode 100644 index 0000000..99a4d8d --- /dev/null +++ b/src/editAttributes/Application.jsx @@ -0,0 +1,42 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import React, {Component} from 'react'; +import {Provider} from 'react-redux'; +import store from 'editAttributes/AppStore.js'; + + +class Application extends Component { + + render() { + return ( + <Provider store={store}> + {this.props.children} + </Provider> + ); + } +} + +export default Application; diff --git a/src/editAttributes/EditAttributeActions.js b/src/editAttributes/EditAttributeActions.js new file mode 100644 index 0000000..871260a --- /dev/null +++ b/src/editAttributes/EditAttributeActions.js @@ -0,0 +1,97 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import NetworkCalls from './networking/NetworkCalls.js'; +import { + POST, + BACKEND_POST_HEADER, + CREDENTIALS +} from './networking/NetworkConstants.js'; +import { + createEditEntityAttributeRequestObject +} from './networking/NetworkUtils.js'; +import { + setAttributesActionTypes, + EDIT_ENTITY_ATTRIBUTES_URL, + RESPONSE_CODE_SUCCESS, + RESPONSE_CODE_NOT_AUTHORIZED, + RESPONSE_MESSAGE_SUCCESS, + RESPONSE_MESSAGE_NOT_AUTHORIZED, + RESPONSE_MESSAGE_FAILURE, + RESPONSE_MESSAGE_NETWORK_ERROR +} from './EditAttributeConstants.js'; + +function errorReturnedEvent(errorMsg) { + return { + type: setAttributesActionTypes.SET_ATTRIBUTE_ERROR, + data: {errorMsg: errorMsg} + }; +} + +function successReturnedEvent() { + return { + type: setAttributesActionTypes.SET_ATTRIBUTE_SUCCESS, + data: {successMsg: RESPONSE_MESSAGE_SUCCESS} + }; +} + +function clearFeedbackMessageEvent() { + return { + type: setAttributesActionTypes.CLEAR_FEEDBACK_MESSAGE, + data: {} + }; +} + +export function clearFeebackMessage() { + return dispatch => { + dispatch(clearFeedbackMessageEvent()); + }; +} + +export function requestEditEntityAttributes(entityURI, entityAttributes) { + + let postBody = JSON.stringify( + createEditEntityAttributeRequestObject(entityURI, entityAttributes)); + return dispatch => { + return NetworkCalls.fetchRequest(EDIT_ENTITY_ATTRIBUTES_URL, + CREDENTIALS, POST, BACKEND_POST_HEADER, postBody).then( + (responseJson) => { + if (responseJson) { + if (responseJson.resultCode === RESPONSE_CODE_SUCCESS) { + dispatch(successReturnedEvent()); + } else if (responseJson.resultCode === RESPONSE_CODE_NOT_AUTHORIZED) { + dispatch(errorReturnedEvent(RESPONSE_MESSAGE_NOT_AUTHORIZED)); + } else { + dispatch(errorReturnedEvent(RESPONSE_MESSAGE_FAILURE)); + } + } + } + ).catch( + () => { + dispatch(errorReturnedEvent(RESPONSE_MESSAGE_NETWORK_ERROR)); + } + ); + }; +} diff --git a/src/editAttributes/EditAttributeConstants.js b/src/editAttributes/EditAttributeConstants.js new file mode 100644 index 0000000..3371091 --- /dev/null +++ b/src/editAttributes/EditAttributeConstants.js @@ -0,0 +1,50 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import keyMirror from 'utils/KeyMirror.js'; +import { + BASE_URL +} from './networking/NetworkConstants.js'; + +export const SET_ATTRIBUTE_TITLE = 'A&AI'; +export const ATTRIBUTE_MODIFICATION = 'ATTRIBUTE MODIFICATION'; + + + +export const EDIT_ENTITY_ATTRIBUTES_URL = BASE_URL + '/editEntity/editAttributes'; + +export const RESPONSE_CODE_SUCCESS = 200; +export const RESPONSE_CODE_NOT_AUTHORIZED = 403; + +export const RESPONSE_MESSAGE_SUCCESS = 'Success'; +export const RESPONSE_MESSAGE_NOT_AUTHORIZED = 'User not authorized'; +export const RESPONSE_MESSAGE_FAILURE = 'Failed to update entity'; +export const RESPONSE_MESSAGE_NETWORK_ERROR = 'Network error'; + +export const setAttributesActionTypes = keyMirror({ + SET_ATTRIBUTE_ERROR: null, + SET_ATTRIBUTE_SUCCESS: null, + CLEAR_FEEDBACK_MESSAGE: null +}); diff --git a/src/editAttributes/EditAttributeReducer.js b/src/editAttributes/EditAttributeReducer.js new file mode 100644 index 0000000..5c55435 --- /dev/null +++ b/src/editAttributes/EditAttributeReducer.js @@ -0,0 +1,56 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import {setAttributesActionTypes} from './EditAttributeConstants.js'; +import { + MESSAGE_LEVEL_SUCCESS, + MESSAGE_LEVEL_DANGER +} from 'utils/GlobalConstants.js'; + +export default (state = {}, action) => { + switch (action.type) { + case setAttributesActionTypes.SET_ATTRIBUTE_ERROR: + return { + ...state, + feedbackMsgText: action.data.errorMsg, + feedbackMsgSeverity: MESSAGE_LEVEL_DANGER + }; + + case setAttributesActionTypes.SET_ATTRIBUTE_SUCCESS: + return { + ...state, + feedbackMsgText: action.data.successMsg, + feedbackMsgSeverity: MESSAGE_LEVEL_SUCCESS + }; + + case setAttributesActionTypes.CLEAR_FEEDBACK_MESSAGE: + return { + ...state, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + } + return state; +}; diff --git a/src/editAttributes/EditAttributes.jsx b/src/editAttributes/EditAttributes.jsx new file mode 100644 index 0000000..ab2d391 --- /dev/null +++ b/src/editAttributes/EditAttributes.jsx @@ -0,0 +1,116 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import React, {Component} from 'react'; +import {connect} from 'react-redux'; +import i18n from 'utils/i18n/i18n'; + +import InlineMessage from 'generic-components/InlineMessage/InlineMessage.jsx'; +import { + clearFeebackMessage, + requestEditEntityAttributes +} from './EditAttributeActions.js'; +import { + SET_ATTRIBUTE_TITLE, + ATTRIBUTE_MODIFICATION +} from './EditAttributeConstants.js'; +import ChangeAttributeForm from 'editAttributes/changeAttributeForm/ChangeAttributeForm.jsx'; +import {NO_VALUE_SELECTED} from 'editAttributes/changeAttributeForm/ChangeAttributeFormConstants.js'; + +let mapStateToProps = ({setAttributes}) => { + let { + feedbackMsgText = '', + feedbackMsgSeverity = '' + } = setAttributes; + + return { + feedbackMsgText, + feedbackMsgSeverity + }; +}; + +let mapActionToProps = (dispatch) => { + return { + handleSubmit: (values) => { + let uri = values.uri; + let attrMap = new Map(); + attrMap.set('provStatus', 'prov-status'); + attrMap.set('inMaint', 'in-maint'); + attrMap.set('isClosedLoopDisabled', 'is-closed-loop-disabled'); + + let attributes = {}; + let valueString = JSON.stringify(values); + JSON.parse(valueString, (key, value) => { + if(value !== NO_VALUE_SELECTED) { + let formattedKey = attrMap.get(key); + if(formattedKey !== undefined) { + attributes = { + ...attributes, [formattedKey]: value + }; + } + return value; + } + }); + + dispatch(requestEditEntityAttributes(uri, attributes)); + }, + clearFeedbackMessage: () => { + dispatch(clearFeebackMessage()); + } + }; +}; + +class SetAttribute extends Component { + render() { + let { + feedbackMsgText, + feedbackMsgSeverity, + handleSubmit, + clearFeedbackMessage} = this.props; + return ( + <div> + <div className='header'> + <div className='application-title'>{i18n(SET_ATTRIBUTE_TITLE)}</div> + </div> + <div className='secondary-header'> + <span + className='secondary-title'>{i18n(ATTRIBUTE_MODIFICATION)}</span> + <InlineMessage level={feedbackMsgSeverity} + messageTxt={feedbackMsgText}/> + </div> + + <ChangeAttributeForm + onSubmit={(values) => { + handleSubmit(values); + }} + buttonSelected={() => { + clearFeedbackMessage(); + }}/> + </div> + ); + } +} + +export default connect(mapStateToProps, mapActionToProps)(SetAttribute); diff --git a/src/editAttributes/changeAttributeForm/ChangeAttributeForm.jsx b/src/editAttributes/changeAttributeForm/ChangeAttributeForm.jsx new file mode 100644 index 0000000..34ba98d --- /dev/null +++ b/src/editAttributes/changeAttributeForm/ChangeAttributeForm.jsx @@ -0,0 +1,161 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import React, {Component} from 'react'; +import {Field, Fields, reduxForm, propTypes} from 'redux-form'; +import i18n from 'utils/i18n/i18n'; + +import { + LABEL_NODE_URI, + LABEL_PROV_STATUS, + LABEL_ATTRIBUTES, + LABEL_IN_MAINT, + LABEL_IS_CLOSED_LOOP, + BUTTON_SUBMIT, + BUTTON_CLEAR, + NO_VALUE_SELECTED, + PREPROV, + NVTPROV, + DECOM, + PROV, + CAPPED, + RETIRED, + TRUE, + FALSE +} from './ChangeAttributeFormConstants.js'; +import validate from './validate.js'; + +class ChangeAttributeForm extends Component { + + static propTypes = { + ...propTypes + }; + + renderTextField = ({input, label, type, meta: {touched, error}}) => ( + <div className='attribute-field'> + <label>{label}</label> + <div> + <input {...input} placeholder={label} type={type} + onBlur={() => input.value === '' ? input.onBlur(' ') : input.onBlur()}/> + {touched && ((error && <span className='error-message'>{error}</span>))} + </div> + </div> + ); + + + booleanOptions = [ + <option value={NO_VALUE_SELECTED}>{i18n(NO_VALUE_SELECTED)}</option>, + <option value='true'>{i18n(TRUE)}</option>, + <option value='false'>{i18n(FALSE)}</option> + ]; + + provStatusOptions = [ + <option value={NO_VALUE_SELECTED}>{i18n(NO_VALUE_SELECTED)}</option>, + <option value={PREPROV}>{PREPROV}</option>, + <option value={NVTPROV}>{NVTPROV}</option>, + <option value={PROV}>{PROV}</option>, + <option value={CAPPED}>{CAPPED}</option>, + <option value={DECOM}>{DECOM}</option>, + <option value={RETIRED}>{RETIRED}</option> + ]; + + renderAttributeFields = (fields) => ( + <div> + <div className='centre'> + {(fields.provStatus.meta.touched || + fields.inMaint.meta.touched || + fields.isClosedLoopDisabled.meta.touched) && + fields.provStatus.meta.error && + <span className='error-message'>{fields.provStatus.meta.error}</span>} + </div> + <div className='attribute-field'> + <label>{LABEL_PROV_STATUS}</label> + <div> + <select {...fields.provStatus.input}> + {this.provStatusOptions} + </select> + </div> + </div> + <div className='attribute-field'> + <label>{LABEL_IN_MAINT}</label> + <div> + <select {...fields.inMaint.input}> + {this.booleanOptions} + </select> + </div> + </div> + <div className='attribute-field'> + <label>{LABEL_IS_CLOSED_LOOP}</label> + <div> + <select {...fields.isClosedLoopDisabled.input}> + {this.booleanOptions} + </select> + </div> + </div> + </div> + ); + + render() { + const { + handleSubmit, + buttonSelected, + pristine, + reset, + submitting} = this.props; + + return ( + <form onSubmit={handleSubmit}> + <Field name='uri' type='text' component={this.renderTextField} + label={i18n(LABEL_NODE_URI)}/> + <div className='centre'><h2>{i18n(LABEL_ATTRIBUTES)}</h2></div> + <Fields names={['provStatus', 'inMaint', 'isClosedLoopDisabled']} + component={this.renderAttributeFields}/> + <div className='centre'> + <button type='submit' + disabled={pristine || submitting} + onClick={() => { + buttonSelected(); + }}> + {i18n(BUTTON_SUBMIT)} + </button> + <button type='button' + disabled={pristine || submitting} + onClick={() => { + reset(); + buttonSelected(); + }}> + {i18n(BUTTON_CLEAR)} + </button> + </div> + </form> + ); + } +} + +export default reduxForm({ + form: 'changeAttributeForm', + validate +})(ChangeAttributeForm); + diff --git a/src/editAttributes/changeAttributeForm/ChangeAttributeFormConstants.js b/src/editAttributes/changeAttributeForm/ChangeAttributeFormConstants.js new file mode 100644 index 0000000..02e8996 --- /dev/null +++ b/src/editAttributes/changeAttributeForm/ChangeAttributeFormConstants.js @@ -0,0 +1,46 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +export const LABEL_NODE_URI = 'Target Entity URI'; +export const LABEL_PROV_STATUS = 'prov-status'; +export const LABEL_IN_MAINT = 'in-maint'; +export const LABEL_IS_CLOSED_LOOP = 'is-closed-loop-disabled'; +export const LABEL_ATTRIBUTES = 'ATTRIBUTES'; + +export const BUTTON_SUBMIT = 'Submit'; +export const BUTTON_CLEAR = 'Clear'; + +export const NO_VALUE_SELECTED = 'No Value Selected'; +export const PREPROV = 'PREPROV'; +export const NVTPROV = 'NVTPROV'; +export const PROV = 'PROV'; +export const CAPPED = 'CAPPED'; +export const DECOM = 'DECOM'; +export const RETIRED = 'RETIRED'; +export const TRUE = 'TRUE'; +export const FALSE = 'FALSE'; + +export const ERROR_MISSING_ATTR = 'At least one attribute must be set'; +export const ERROR_REQUIRED = 'Required'; diff --git a/src/editAttributes/changeAttributeForm/ChangeAttributeFormReducer.js b/src/editAttributes/changeAttributeForm/ChangeAttributeFormReducer.js new file mode 100644 index 0000000..0778a0e --- /dev/null +++ b/src/editAttributes/changeAttributeForm/ChangeAttributeFormReducer.js @@ -0,0 +1,38 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +/*import { combineReducers } from 'redux' + import { reducer as formReducer } from 'redux-form' + + + + const reducer = combineReducers({ + form: formReducer.validation({ + changeAttributeForm: validate + }) + }); + + export default reducer; + */ diff --git a/src/editAttributes/changeAttributeForm/validate.js b/src/editAttributes/changeAttributeForm/validate.js new file mode 100644 index 0000000..d6a8d99 --- /dev/null +++ b/src/editAttributes/changeAttributeForm/validate.js @@ -0,0 +1,51 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import i18n from 'utils/i18n/i18n'; + +import { + ERROR_MISSING_ATTR, + ERROR_REQUIRED, + NO_VALUE_SELECTED +} from './ChangeAttributeFormConstants.js'; + +const validate = (values) => { + const errors = {}; + + if (!values.uri || values.uri.replace(/\s/g, '') === '') { + errors.uri = i18n(ERROR_REQUIRED); + } + if ((!values.provStatus || values.provStatus === NO_VALUE_SELECTED) && + (!values.inMaint || values.inMaint === NO_VALUE_SELECTED) && + (!values.isClosedLoopDisabled || + values.isClosedLoopDisabled === + NO_VALUE_SELECTED)) { + errors.provStatus = i18n(ERROR_MISSING_ATTR); + } + + return errors; +}; + +export default validate; diff --git a/src/editAttributes/index.html b/src/editAttributes/index.html new file mode 100644 index 0000000..45c0d04 --- /dev/null +++ b/src/editAttributes/index.html @@ -0,0 +1,12 @@ +<html> +<head> + <meta charset="utf-8"> + <title>Edit Attributes</title> +</head> + +<body> +<div id="set-attribute-app"></div> +</body> + +<script src="editAttributesBundle.js"></script> +</html> diff --git a/src/editAttributes/main.app.jsx b/src/editAttributes/main.app.jsx new file mode 100644 index 0000000..b760db0 --- /dev/null +++ b/src/editAttributes/main.app.jsx @@ -0,0 +1,38 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import React from 'react'; +import ReactDOM from 'react-dom'; + +import 'resources/scss/bootstrap.scss'; +import 'resources/css/font-awesome.min.css'; +import 'resources/scss/style.scss'; + +import Application from './Application.jsx'; +import SetAttribute from './EditAttributes.jsx'; + +ReactDOM.render( + <Application><SetAttribute /></Application>, + document.getElementById('set-attribute-app')); diff --git a/src/editAttributes/networking/NetworkCalls.js b/src/editAttributes/networking/NetworkCalls.js new file mode 100644 index 0000000..a107aa6 --- /dev/null +++ b/src/editAttributes/networking/NetworkCalls.js @@ -0,0 +1,37 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +export default { + fetchRequest(URL, CREDENTIALS, METHOD, HEADER, BODY) { + return fetch(URL, { + credentials: CREDENTIALS, + method: METHOD, + headers: HEADER, + body: BODY + }).then( + (response) => response.json() + ); + } +}; diff --git a/src/editAttributes/networking/NetworkConstants.js b/src/editAttributes/networking/NetworkConstants.js new file mode 100644 index 0000000..d20882d --- /dev/null +++ b/src/editAttributes/networking/NetworkConstants.js @@ -0,0 +1,39 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +export const POST = 'POST'; +export const POST_HEADER = { + 'Accept': 'application/json' +}; +export const BACKEND_POST_HEADER = { + 'Accept': 'application/json', + 'Content-Type': 'application/json' +}; +export const CREDENTIALS = 'same-origin'; +export const ERROR_RETRIEVING_DATA = 'Error fetching data from server'; +const BACKEND_IP_ADDRESS = document.location.hostname; +const BACKEND_PORT_NUMBER = window.location.port; +const PROTOCOL = window.location.protocol; +export const BASE_URL = PROTOCOL + '//' + BACKEND_IP_ADDRESS + ':' + BACKEND_PORT_NUMBER; diff --git a/src/editAttributes/networking/NetworkUtils.js b/src/editAttributes/networking/NetworkUtils.js new file mode 100644 index 0000000..8fa50b8 --- /dev/null +++ b/src/editAttributes/networking/NetworkUtils.js @@ -0,0 +1,34 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + + +export function createEditEntityAttributeRequestObject(uri, attributes) { + return { + 'entity-uri': uri, + 'attributes': { + ...attributes + } + }; +} diff --git a/src/generic-components/autoCompleteSearchBar/AutoCompleteSearchBar.jsx b/src/generic-components/autoCompleteSearchBar/AutoCompleteSearchBar.jsx index 455a3ab..bd71e66 100644 --- a/src/generic-components/autoCompleteSearchBar/AutoCompleteSearchBar.jsx +++ b/src/generic-components/autoCompleteSearchBar/AutoCompleteSearchBar.jsx @@ -1,25 +1,28 @@ /* - * ============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 {Button} from 'react-bootstrap'; import AutoSuggest from 'react-autosuggest'; @@ -120,6 +123,7 @@ export default class AutoCompleteSearchBar extends Component { onSuggestionsClearRequested={onSuggestionsClearRequested} onSuggestionSelected={(event, {suggestion}) => { this.newSearchSelected(suggestion, onInvalidSearch, dispatchAnalytics, value); + this.props.onClearSuggestionsTextFieldRequested(); }} renderSuggestion={this.renderSuggestion} inputProps={inputProps} @@ -134,6 +138,7 @@ export default class AutoCompleteSearchBar extends Component { <Button type='submit' className='auto-complete-search-button' onClick={() => { this.newSearchSelected(this.getSelectedSuggestionObj(value, cachedSuggestions), onInvalidSearch, dispatchAnalytics, value); + this.props.onSuggestionsClearRequested(); }}> <i className={ICON_CLASS_SEARCH} aria-hidden='true'/> </Button> diff --git a/src/generic-components/dynamicViewLoader/DynamicViewLoaderReducer.js b/src/generic-components/dynamicViewLoader/DynamicViewLoaderReducer.js index c117fc5..969f645 100644 --- a/src/generic-components/dynamicViewLoader/DynamicViewLoaderReducer.js +++ b/src/generic-components/dynamicViewLoader/DynamicViewLoaderReducer.js @@ -1,32 +1,33 @@ /* - * ============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 {combineReducers} from 'redux'; -import DateRangeSelectorReducer from 'generic-components/dateRangeSelector/DateRangeSelectorReducer.js'; import {dynamicViewLoaderActionTypes} from 'generic-components/dynamicViewLoader/DynamicViewLoaderConstants.js'; export default combineReducers({ - dateRangeSelectorData: DateRangeSelectorReducer, dynamicViewLoadData: (state = {}, action) => { switch (action.type) { case dynamicViewLoaderActionTypes.DVL_LAYOUT_SOURCE_CHANGE: diff --git a/src/generic-components/filterBar/FilterBarConstants.js b/src/generic-components/filterBar/FilterBarConstants.js new file mode 100644 index 0000000..4226774 --- /dev/null +++ b/src/generic-components/filterBar/FilterBarConstants.js @@ -0,0 +1,58 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import keyMirror from 'utils/KeyMirror.js'; +import {BASE_URL} from 'app/networking/NetworkConstants.js'; + +export const filterBarActionTypes = keyMirror({ + SET_FILTERS: null, + SET_FILTER_VALUES: null, + CLEAR_FILTERS: null, + FILTER_VALUE_CHANGE: null, + NEW_SELECTIONS: null, + SET_NON_CONVERTED_VALUES: null, + SET_CONVERTED_VALUES: null, + SET_UNIFIED_VALUES: null +}); + +export const UNIFIED_FILTERS_URL = BASE_URL + '/rest/search/unifiedFilterRequest'; + +export const DISCOVER_FILTERS_ERROR_MSG = 'There was an error retrieving the' + + ' list of available filters'; + +export const FILTER_BAR_TITLE = 'FILTER BY'; +export const DATE_TIME_ZONE = 'Z'; + +export const FILTER_TYPE_ENUM = { + LIST: 'dropDown', + DATE: 'date' +}; + +export const FILTER_ATTRIBUTE_DEFAULT_VALUE = 'defaultValue'; +export const FILTER_ATTRIBUTE_CONTROLS = 'controls'; +export const FILTER_ATTRIBUTE_CODE = 'code'; +export const FILTER_ATTRIBUTE_VALUES = 'values'; +export const FILTER_ATTRIBUTE_TO = 'to'; +export const FILTER_ATTRIBUTE_FROM = 'from'; diff --git a/src/generic-components/filterBar/FilterBarUtils.js b/src/generic-components/filterBar/FilterBarUtils.js new file mode 100644 index 0000000..982bda9 --- /dev/null +++ b/src/generic-components/filterBar/FilterBarUtils.js @@ -0,0 +1,352 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ +import isEmpty from 'lodash/isEmpty'; +import moment from 'moment-timezone'; +import { + POST, + POST_HEADER +} from 'app/networking/NetworkConstants.js'; +import { + UNIFIED_FILTERS_URL, + DISCOVER_FILTERS_ERROR_MSG, + DATE_TIME_ZONE, + FILTER_ATTRIBUTE_TO, + FILTER_ATTRIBUTE_FROM, + FILTER_ATTRIBUTE_CODE, + FILTER_ATTRIBUTE_VALUES, + FILTER_ATTRIBUTE_CONTROLS, + FILTER_ATTRIBUTE_DEFAULT_VALUE, + FILTER_TYPE_ENUM, + filterBarActionTypes +} from 'generic-components/filterBar/FilterBarConstants.js'; +import { + MESSAGE_LEVEL_WARNING +} from 'utils/GlobalConstants.js'; +import { + getSetGlobalMessageEvent +} from 'app/globalInlineMessageBar/GlobalInlineMessageBarActions.js'; + +export function buildFilterValueMap(filterValueString) { + let filterValueObj = {}; + let filters = filterValueString.split(','); + + for (let filterIndex in filters) { + let filterStringParts = filters[filterIndex].split('='); + + filterValueObj[filterStringParts[0]] = filterStringParts[1]; + } + + return filterValueObj; +} + +export function buildFilterValueMapFromObj(filterValues) { + let filterValueObj = {}; + + for (let filterIndex in filterValues) { + filterValueObj[filterValues[filterIndex].filterId] = filterValues[filterIndex].filterValue; + } + + return filterValueObj; +} + +export function getFilterListQueryString(filterValueList) { + let filterQueryList = []; + + for (let filter in filterValueList) { + if (filterValueList[filter]) { + filterQueryList.push( + { + 'filterId': filter, + 'filterValue': filterValueList[filter] + } + ); + } + } + + return filterQueryList; +} + +function getFilterSearchURL() { + return UNIFIED_FILTERS_URL.replace('@@IP-ADDRESS@@', document.location.hostname); +} + +function getFiltersQueryObject(viewName) { + return { + 'viewName': viewName + }; +} + +function getFiltersEvent(actionType, filterList) { + return { + type: actionType, + data: filterList + }; +} + +export function getUnifiedFilters(viewName, actionType) { + return dispatch => { + return fetch(getFilterSearchURL(), { + credentials: 'same-origin', + method: POST, + headers: POST_HEADER, + body: JSON.stringify(getFiltersQueryObject(viewName)) + }).then( + (response) => response.json() + ).then( + (responseJson) => { + dispatch( + getFiltersEvent(actionType, responseJson.filters) + ); + } + ).catch( + () => { + dispatch(getSetGlobalMessageEvent(DISCOVER_FILTERS_ERROR_MSG, MESSAGE_LEVEL_WARNING)); + } + ); + }; +} + +function extractConvertedDateValues(dateValues) { + let convertedValues = {}; + if (dateValues.from) { + let startMoment = moment(dateValues.from); + convertedValues.startDate = startMoment.toDate(); + convertedValues.time_zone = startMoment.format(DATE_TIME_ZONE); + } + + if (dateValues.to) { + let endMoment = moment(dateValues.to); + convertedValues.endDate = endMoment.toDate(); + convertedValues.time_zone = endMoment.format(DATE_TIME_ZONE); + } + + convertedValues.code = dateValues.code; + + return convertedValues; +} + +function convertFilterValues(filterValues) { + let convertedFilterValues = {}; + + for (let filterId in filterValues) { + if (filterValues.hasOwnProperty(filterId) && + !isEmpty(filterValues[filterId]) && !isEmpty(filterValues[filterId].controls)) { + let controls = filterValues[filterId].controls; + let firstControlKey = Object.keys(controls)[0]; + if (controls[firstControlKey][FILTER_ATTRIBUTE_VALUES][FILTER_ATTRIBUTE_FROM] || + controls[firstControlKey][FILTER_ATTRIBUTE_VALUES][FILTER_ATTRIBUTE_TO]) { + // TODO should check against filter type (ex: dropdown or date) + // rather than assuming value attributes (ex: 'to' or 'from') + convertedFilterValues[filterId] = + extractConvertedDateValues(controls[firstControlKey][FILTER_ATTRIBUTE_VALUES]); + } else { + let codeValue = controls[firstControlKey][FILTER_ATTRIBUTE_VALUES][FILTER_ATTRIBUTE_CODE]; + convertedFilterValues[filterId] = codeValue; + } + } + } + + return convertedFilterValues; +} + +function combineMissingFilters(filterValues, allFilters) { + let allFilterIds = Object.keys(allFilters); + + for (let id in allFilterIds) { + if (!filterValues.hasOwnProperty(allFilterIds[id])) { + filterValues[allFilterIds[id]] = ''; + } + } + + return filterValues; +} + +function getFilterSelectionEvent(selectedValuesMap, convertedValues) { + return { + type: filterBarActionTypes.NEW_SELECTIONS, + data: { + selectedValuesMap: convertedValues, + unifiedValues: selectedValuesMap + } + }; +} + +export function processFilterSelection(filterValues, allFilters) { + let convertedFilterValues = convertFilterValues(filterValues); + let combinedFilterValues = combineMissingFilters(convertedFilterValues, allFilters); + + // dispatch NEW_SELECTION event type with converted values as the data + return getFilterSelectionEvent(filterValues, combinedFilterValues); +} + +export function setNonConvertedFilterValues(nonConvertedValues) { + return { + type: filterBarActionTypes.SET_NON_CONVERTED_VALUES, + data: nonConvertedValues + }; +} + +function convertedFilterValuesEvent(nonConvertedValues, convertedValues) { + return { + type: filterBarActionTypes.SET_CONVERTED_VALUES, + data: { + nonConvertedValues: nonConvertedValues, + convertedValues: convertedValues + } + }; +} + +function mapValuesToOption(filterOptions, nonConvertedValue) { + let mappedValues = {}; + + // loop over options to find match for value + for (let i in filterOptions) { + if (filterOptions[i].code === nonConvertedValue) { + // found the matching + mappedValues = filterOptions[i]; + break; + } + } + + return mappedValues; +} + +function mapValuesToDateOption(nonConvertedValue) { + let mappedValues = {}; + + if (nonConvertedValue.startDate) { + mappedValues.from = new Date(nonConvertedValue.startDate); + } else { + mappedValues.from = null; + } + + if (nonConvertedValue.endDate) { + mappedValues.to = new Date(nonConvertedValue.endDate); + } else { + mappedValues.to = null; + } + + mappedValues.code = nonConvertedValue.code; + + return mappedValues; +} + +function mapValuesToFilter(nonConvertedValues, allFilters, currentlySetFilterValues) { + let convertedValues = {}; + + for (let nonConvertedId in nonConvertedValues) { + if (nonConvertedValues[nonConvertedId] !== '') { + let matchingFilterObj = allFilters[nonConvertedId]; + let filterControlId = Object.keys(matchingFilterObj.controls)[0]; + let mappedValue = {}; + + if (matchingFilterObj[FILTER_ATTRIBUTE_CONTROLS][filterControlId].type === FILTER_TYPE_ENUM.DATE) { + mappedValue = mapValuesToDateOption(nonConvertedValues[nonConvertedId]); + } else { + mappedValue = mapValuesToOption(matchingFilterObj[FILTER_ATTRIBUTE_CONTROLS][filterControlId].options, + nonConvertedValues[nonConvertedId]); + } + + let values = {}; + values[FILTER_ATTRIBUTE_VALUES] = mappedValue; + let filterControlers = {}; + filterControlers[filterControlId] = values; + let filter = {}; + filter[FILTER_ATTRIBUTE_CONTROLS] = filterControlers; + convertedValues[nonConvertedId] = filter; + } else if (!isEmpty(currentlySetFilterValues[nonConvertedId])) { + // currently a value is set for this filter, need to ensure we map this filter + // to an empty value so that it is cleared/reset + let matchingFilterObj = allFilters[nonConvertedId]; + let filterControlId = Object.keys(matchingFilterObj.controls)[0]; + let mappedValue = {}; + let values = {}; + values[FILTER_ATTRIBUTE_VALUES] = mappedValue; + let filterControlers = {}; + filterControlers[filterControlId] = values; + let filter = {}; + filter[FILTER_ATTRIBUTE_CONTROLS] = filterControlers; + convertedValues[nonConvertedId] = filter; + } + } + + return convertedValues; +} + +export function convertNonConvertedValues(nonConvertedValues, allFilters, currentlySetFilterValues) { + let convertedValues = mapValuesToFilter(nonConvertedValues, allFilters, currentlySetFilterValues); + return convertedFilterValuesEvent(nonConvertedValues, convertedValues); +} + +export function clearFilters() { + return { + type: filterBarActionTypes.CLEAR_FILTERS + }; +} + +function getSetUnifiedFilterValuesEvent(unifiedValues) { + return { + type: filterBarActionTypes.SET_UNIFIED_VALUES, + data: unifiedValues + }; +} + +function getFilterDefault(filters, filterId) { + let filterControlId = Object.keys(filters[filterId][FILTER_ATTRIBUTE_CONTROLS])[0]; + let defaultValue = filters[filterId][FILTER_ATTRIBUTE_CONTROLS][filterControlId][FILTER_ATTRIBUTE_DEFAULT_VALUE]; + if (!defaultValue) { + defaultValue = {}; + } + return defaultValue; +} + +export function setFilterSelectionsToDefaults(filters, filterValues) { + let defaultFilterMap = {}; + + for (let filterId in filters) { + let filterDefaultValue = getFilterDefault(filters, filterId); + if (!isEmpty(filterDefaultValue) || (filterValues && filterValues[filterId])) { + let filterControlId = Object.keys(filters[filterId][FILTER_ATTRIBUTE_CONTROLS])[0]; + let controller = {}; + controller.values = filterDefaultValue; + let controllers = {}; + controllers[filterControlId] = controller; + let controls = {}; + controls.controls = controllers; + defaultFilterMap[filterId] = controls; + } + } + + if (isEmpty(defaultFilterMap)) { + // there are no default values, so need to ensure all filters get cleared, + // but just incase this 'clearing' + let combinedValues = combineMissingFilters(defaultFilterMap, filters); + return setNonConvertedFilterValues(combinedValues); + } else { + // jsut set the Unified Filter Value which will be sent down to the filter (filter + // will set itself to the default value and then send notification back up of the selection + return getSetUnifiedFilterValuesEvent(defaultFilterMap); + } +} diff --git a/src/generic-components/graph/ForceDirectedGraph.jsx b/src/generic-components/graph/ForceDirectedGraph.jsx index 872b2d5..00c2575 100644 --- a/src/generic-components/graph/ForceDirectedGraph.jsx +++ b/src/generic-components/graph/ForceDirectedGraph.jsx @@ -1,25 +1,28 @@ /* - * ============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 {drag} from 'd3-drag'; import {forceSimulation, forceLink, forceManyBody, forceCenter} from 'd3-force'; import {interpolateNumber} from 'd3-interpolate'; @@ -44,7 +47,7 @@ class ForceDirectedGraph extends Component { nodeButtonSelectedCallback: PropTypes.func, currentlySelectedNodeView: PropTypes.string }; - + static defaultProps = { viewWidth: 0, viewHeight: 0, @@ -57,16 +60,16 @@ class ForceDirectedGraph extends Component { nodeButtonSelectedCallback: undefined, currentlySelectedNodeView: '' }; - + constructor(props) { super(props); - + this.state = { nodes: [], links: [], mainGroupTransform: zoomIdentity }; - + this.updateSimulationForce = this.updateSimulationForce.bind(this); - this.resetTransform = this.resetTransform.bind(this); + this.resetState = this.resetState.bind(this); this.applyBufferDataToState = this.applyBufferDataToState.bind(this); this.createNodePropForState = this.createNodePropForState.bind(this); this.createLinkPropForState = this.createLinkPropForState.bind(this); @@ -74,118 +77,138 @@ class ForceDirectedGraph extends Component { this.simulationComplete = this.simulationComplete.bind(this); this.simulationTick = this.simulationTick.bind(this); this.nodeSelected = this.nodeSelected.bind(this); + this.nodeButtonSelected = this.nodeButtonSelected.bind(this); this.onZoom = this.onZoom.bind(this); this.onGraphDrag = this.onGraphDrag.bind(this); this.onNodeDrag = this.onNodeDrag.bind(this); this.addNodeInterpolator = this.addNodeInterpolator.bind(this); this.runInterpolators = this.runInterpolators.bind(this); - + this.nodeBuffer = []; this.linkBuffer = []; this.nodeDatum = []; this.nodeButtonDatum = []; this.nodeFactory = new NodeFactory(); this.visualElementFactory = new NodeVisualElementFactory(); - + this.isGraphMounted = false; - + this.listenerGraphCounter = -1; this.nodeIndexTracker = new Map(); this.interpolators = new Map(); this.areInterpolationsRunning = false; - + this.newNodeSelected = true; this.currentlySelectedNodeButton = undefined; - + this.intervalTimer = interval(this.applyBufferDataToState, simulationKeys.DATA_COPY_INTERVAL); this.intervalTimer.stop(); - + this.interpolationTimer = interval(this.runInterpolators, simulationKeys.DATA_COPY_INTERVAL); this.interpolationTimer.stop(); - + this.simulation = forceSimulation(); this.simulation.on('end', this.simulationComplete); this.simulation.stop(); - + this.svgZoom = zoom().scaleExtent([NodeConstants.SCALE_EXTENT_MIN, NodeConstants.SACEL_EXTENT_MAX]); this.svgZoom.clickDistance(2); this.nodeDrag = drag().clickDistance(2); - + this.updateSimulationForce(); - + // Temporary code until backend supports NOT displaying the button in the response. + if(props.dataOverlayButtons.length === 1) { + this.hideButton = true; + } else { + this.hideButton = false; + } if (props.graphData) { if (props.graphData.graphCounter !== -1) { - this.startSimulation(props.graphData); + this.startSimulation(props.graphData, props.currentlySelectedNodeView, props.dataOverlayButtons); } } } - + componentDidMount() { this.isGraphMounted = true; } - + componentWillReceiveProps(nextProps) { if (nextProps.graphData.graphCounter !== this.props.graphData.graphCounter) { this.listenerGraphCounter = this.props.graphData.graphCounter; this.newNodeSelected = true; - this.resetTransform(); - this.startSimulation(nextProps.graphData); + this.resetState(); + this.startSimulation(nextProps.graphData, nextProps.currentlySelectedNodeView, nextProps.dataOverlayButtons); } } - + + componentDidUpdate(prevProps) { let hasNewGraphDataRendered = (prevProps.graphData.graphCounter === this.props.graphData.graphCounter); let shouldAttachListeners = (this.listenerGraphCounter !== this.props.graphData.graphCounter); let nodeCount = this.state.nodes.length; - + if (nodeCount > 0) { if (hasNewGraphDataRendered && shouldAttachListeners) { - let nodes = select('.fdgMainSvg').select('.fdgMainG') .selectAll('.aai-entity-node') .data(this.nodeDatum); - nodes.on('click', (d) => { this.nodeSelected(d); }); - + nodes.call(this.nodeDrag.on('drag', (d) => { let xAndY = [currentEvent.x, currentEvent.y]; this.onNodeDrag(d, xAndY); })); - + let mainSVG = select('.fdgMainSvg'); let mainView = mainSVG.select('.fdgMainView'); this.svgZoom.transform(mainSVG, zoomIdentity); this.svgZoom.transform(mainView, zoomIdentity); - + mainSVG.call(this.svgZoom.on('zoom', () => { // D3 Zoom also handles panning this.onZoom(currentEvent.transform); })).on('dblclick.zoom', null); // Ignore the double-click zoom event - + this.listenerGraphCounter = this.props.graphData.graphCounter; } + + if (this.newNodeSelected) { + let nodeButtons = select('.fdgMainSvg').select('.fdgMainG') + .selectAll('.aai-entity-node') + .selectAll('.node-button') + .data(this.nodeButtonDatum); + if (!nodeButtons.empty()) { + nodeButtons.on('click', (d) => { + this.nodeButtonSelected(d); + }); + if (hasNewGraphDataRendered && shouldAttachListeners) { + this.newNodeSelected = false; + } + } + } } } - + componentWillUnmount() { this.isGraphMounted = false; - + let nodes = select('.fdgMainSvg').select('.fdgMainG') .selectAll('.aai-entity-node'); let nodeButtons = nodes.selectAll('.node-button'); - + nodes.on('click', null); nodeButtons.on('click', null); - + let mainSVG = select('.fdgMainSvg'); - + mainSVG.call(this.svgZoom.on('zoom', null)).on('dblclick.zoom', null); mainSVG.call(drag().on('drag', null)); } - + updateSimulationForce() { this.simulation.force('link', forceLink()); this.simulation.force('link').id((d) => { @@ -193,55 +216,65 @@ class ForceDirectedGraph extends Component { }); this.simulation.force('link').strength(0.3); this.simulation.force('link').distance(100); - + this.simulation.force('charge', forceManyBody()); this.simulation.force('charge').strength(-1250); this.simulation.alpha(1); - + this.simulation.force('center', forceCenter(this.props.viewWidth / 2, this.props.viewHeight / 2)); } - - resetTransform() { + + resetState() { if (this.isGraphMounted) { this.setState(() => { return { - mainGroupTransform: zoomIdentity + mainGroupTransform: zoomIdentity, + nodes: [], links: [] }; }); } } - + applyBufferDataToState() { this.nodeIndexTracker.clear(); - + let newNodes = []; this.nodeBuffer.map((node, i) => { let nodeProps = this.createNodePropForState(node); - - if (nodeProps.meta.nodeMeta.className === NodeConstants.SELECTED_NODE_CLASS_NAME || - nodeProps.meta.nodeMeta.className === NodeConstants.SELECTED_SEARCHED_NODE_CLASS_NAME) { - + + if (nodeProps.meta.nodeMeta.className === + NodeConstants.SELECTED_NODE_CLASS_NAME || + nodeProps.meta.nodeMeta.className === + NodeConstants.SELECTED_SEARCHED_NODE_CLASS_NAME) { + this.nodeButtonDatum[0].data = nodeProps.meta; - - nodeProps = { - ...nodeProps, - buttons: [this.nodeButtonDatum[0].isSelected] - }; + if(this.nodeButtonDatum.length > 1) { + this.nodeButtonDatum[1].data = nodeProps.meta; + nodeProps = { + ...nodeProps, + buttons: [this.nodeButtonDatum[0].isSelected, this.nodeButtonDatum[1].isSelected] + }; + } else { + nodeProps = { + ...nodeProps, + buttons: [this.nodeButtonDatum[0].isSelected] + }; + } } - - newNodes.push(this.nodeFactory.buildNode(nodeProps.meta.nodeMeta.className, nodeProps)); - + + newNodes.push(this.nodeFactory.buildNode(nodeProps.meta.nodeMeta.className, nodeProps, this.hideButton)); + this.nodeIndexTracker.set(node.id, i); }); - + let newLinks = []; this.linkBuffer.map((link) => { let key = link.id; let linkProps = this.createLinkPropForState(link); newLinks.push(this.visualElementFactory.createSvgLine(linkProps, key)); }); - + if (this.isGraphMounted) { this.setState(() => { return { @@ -250,7 +283,7 @@ class ForceDirectedGraph extends Component { }); } } - + createNodePropForState(nodeData) { return { renderProps: { @@ -260,7 +293,7 @@ class ForceDirectedGraph extends Component { } }; } - + createLinkPropForState(linkData) { return { className: 'aai-entity-link', @@ -270,10 +303,10 @@ class ForceDirectedGraph extends Component { y2: linkData.target.y }; } - - startSimulation(graphData) { + + startSimulation(graphData, currentView, overlayButtons) { this.nodeFactory.setNodeMeta(graphData.graphMeta); - + // Experiment with removing length = 0... might not be needed as new array // assignment will likely destroy old reference this.nodeBuffer.length = 0; @@ -282,45 +315,60 @@ class ForceDirectedGraph extends Component { this.linkBuffer = Array.from(graphData.linkDataArray); this.nodeDatum.length = 0; this.nodeDatum = Array.from(graphData.nodeDataArray); - + this.nodeButtonDatum.length = 0; - - let isNodeDetailsSelected = true; + + let isNodeDetailsSelected = (currentView === + overlayButtons[0] || + currentView === + ''); this.nodeButtonDatum.push({ - name: NodeConstants.ICON_ELLIPSES, isSelected: isNodeDetailsSelected + name: NodeConstants.ICON_ELLIPSES, isSelected: isNodeDetailsSelected, overlayName: overlayButtons[0] }); - + + + if(overlayButtons.length > 1 ) { + let isSecondButtonSelected = (currentView === overlayButtons[1]); + + this.nodeButtonDatum.push({ + name: NodeConstants.ICON_TRIANGLE_WARNING, isSelected: isSecondButtonSelected, overlayName: overlayButtons[1] + }); + } + + if (isNodeDetailsSelected) { this.currentlySelectedNodeButton = NodeConstants.ICON_ELLIPSES; + } else { + this.currentlySelectedNodeButton = NodeConstants.ICON_TRIANGLE_WARNING; } - + this.updateSimulationForce(); - + this.simulation.nodes(this.nodeBuffer); this.simulation.force('link').links(this.linkBuffer); this.simulation.on('tick', this.simulationTick); this.simulation.restart(); } - + simulationComplete() { this.intervalTimer.stop(); this.applyBufferDataToState(); } - + simulationTick() { this.intervalTimer.restart(this.applyBufferDataToState, simulationKeys.DATA_COPY_INTERVAL); this.simulation.on('tick', null); } - + nodeSelected(datum) { if (this.props.nodeSelectedCallback) { this.props.nodeSelectedCallback(datum); } - + let didUpdateNew = false; let didUpdatePrevious = false; let isSameNodeSelected = true; - + // Check to see if a default node was previously selected let selectedDefaultNode = select('.fdgMainSvg').select('.fdgMainG') .selectAll('.aai-entity-node') @@ -333,7 +381,7 @@ class ForceDirectedGraph extends Component { isSameNodeSelected = false; } } - + // Check to see if a searched node was previously selected let selectedSearchedNode = select('.fdgMainSvg').select('.fdgMainG') .selectAll('.aai-entity-node') @@ -346,7 +394,7 @@ class ForceDirectedGraph extends Component { isSameNodeSelected = false; } } - + if (!isSameNodeSelected) { let newlySelectedNode = select('.fdgMainSvg').select('.fdgMainG') .selectAll('.aai-entity-node') @@ -354,7 +402,7 @@ class ForceDirectedGraph extends Component { return (datum.id === d.id); }); if (!newlySelectedNode.empty()) { - + if (newlySelectedNode.datum().nodeMeta.searchTarget) { this.nodeBuffer[newlySelectedNode.datum().index].nodeMeta.className = NodeConstants.SELECTED_SEARCHED_NODE_CLASS_NAME; @@ -365,13 +413,35 @@ class ForceDirectedGraph extends Component { didUpdateNew = true; } } - + if (didUpdatePrevious && didUpdateNew) { this.newNodeSelected = true; this.applyBufferDataToState(); } } + nodeButtonSelected(datum) { + if (this.props.nodeButtonSelectedCallback) { + let buttonClickEvent = { + buttonId: datum.overlayName + }; + this.props.nodeButtonSelectedCallback(buttonClickEvent); + } + + if (this.currentlySelectedNodeButton !== datum.name) { + if (datum.name === this.nodeButtonDatum[0].name) { + this.nodeButtonDatum[0].isSelected = true; + this.nodeButtonDatum[1].isSelected = false; + } + if (datum.name === this.nodeButtonDatum[1].name) { + this.nodeButtonDatum[0].isSelected = false; + this.nodeButtonDatum[1].isSelected = true; + } + this.currentlySelectedNodeButton = datum.name; + this.applyBufferDataToState(); + } + } + onZoom(eventTransform) { if (this.isGraphMounted) { this.setState(() => { @@ -381,7 +451,7 @@ class ForceDirectedGraph extends Component { }); } } - + onGraphDrag(xAndYCoords) { let translate = `translate(${xAndYCoords.x}, ${xAndYCoords.y})`; let oldTransform = this.state.mainGroupTransform; @@ -393,7 +463,7 @@ class ForceDirectedGraph extends Component { }); } } - + onNodeDrag(datum, xAndYCoords) { let nodeIndex = this.nodeIndexTracker.get(datum.id); if (this.nodeBuffer[nodeIndex]) { @@ -402,7 +472,7 @@ class ForceDirectedGraph extends Component { this.applyBufferDataToState(); } } - + addNodeInterpolator(nodeId, key, startingValue, endingValue, duration) { let numberInterpolator = interpolateNumber(startingValue, endingValue); let timeNow = now(); @@ -410,20 +480,20 @@ class ForceDirectedGraph extends Component { nodeId: nodeId, key: key, duration: duration, timeCreated: timeNow, method: numberInterpolator }; this.interpolators.set(nodeId, interpolationObject); - + if (!this.areInterpolationsRunning) { this.interpolationTimer.restart(this.runInterpolators, simulationKeys.DATA_COPY_INTERVAL); this.areInterpolationsRunning = true; } } - + runInterpolators() { // If we have no more interpolators to run then shut'r down! if (this.interpolators.size === 0) { this.interpolationTimer.stop(); this.areInterpolationsRunning = false; } - + let iterpolatorsComplete = []; // Apply interpolation values this.interpolators.forEach((interpolator) => { @@ -439,22 +509,22 @@ class ForceDirectedGraph extends Component { this.nodeBuffer[nodeIndex][interpolator.key] = interpolator.method(t); } }); - + // Remove any interpolators that are complete if (iterpolatorsComplete.length > 0) { for (let i = 0; i < iterpolatorsComplete.length; i++) { this.interpolators.delete(iterpolatorsComplete[i]); } } - + this.applyBufferDataToState(); } - + render() { // We will be using these values veru shortly, commenting out for eslint // reasons so we can build for PV let {viewWidth, viewHeight} = this.props; let {nodes, links, mainGroupTransform} = this.state; - + return ( <div className='ts-force-selected-graph'> <svg className={'fdgMainSvg'} width='100%' height='100%'> @@ -478,9 +548,9 @@ class ForceDirectedGraph extends Component { </div> ); } - + static graphCounter = 0; - + static generateNewProps(nodeArray, linkArray, metaData) { ForceDirectedGraph.graphCounter += 1; return { diff --git a/src/generic-components/graph/NodeFactory.js b/src/generic-components/graph/NodeFactory.js index da57ffb..abfd73b 100644 --- a/src/generic-components/graph/NodeFactory.js +++ b/src/generic-components/graph/NodeFactory.js @@ -1,25 +1,28 @@ /* - * ============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 from 'react'; import NodeVisualElementConstants from './NodeVisualElementConstants.js'; @@ -38,11 +41,11 @@ class NodeFactory { this.graphMeta = metaObject; this.visualElementFactory.setVisualElementMeta(metaObject); } - - buildNode(nodeType, nodeProps) { + // hideButton a temporary solution to not display the button. + buildNode(nodeType, nodeProps, hideButton) { let translate = `translate( - ${nodeProps.renderProps.x}, + ${nodeProps.renderProps.x}, ${nodeProps.renderProps.y})`; let finalProps = { ...nodeProps.renderProps, @@ -51,14 +54,20 @@ class NodeFactory { }; let nodeVisualElementsData = this.extractVisualElementArrayFromMeta( - nodeType); + nodeType, hideButton); let nodeVisualElements = undefined; if (nodeVisualElementsData) { nodeVisualElements = []; nodeVisualElementsData.map((elementData, index) => { if (elementData.type === NodeVisualElementConstants.BUTTON) { if (nodeProps.buttons) { - let isButtonSelected = true; + let isButtonSelected = false; + if (index === 4) { + isButtonSelected = nodeProps.buttons[0]; + } + if (index === 5) { + isButtonSelected = nodeProps.buttons[1]; + } elementData = { ...elementData, isSelected: isButtonSelected @@ -99,11 +108,20 @@ class NodeFactory { return React.createElement('g', finalProps); } - extractVisualElementArrayFromMeta(nodeClassName) { + extractVisualElementArrayFromMeta(nodeClassName, hideButton) { let nodeVisualElements = undefined; if (this.graphMeta.aaiEntityNodeDescriptors) { nodeVisualElements = this.graphMeta.aaiEntityNodeDescriptors[nodeClassName].visualElements; + if(hideButton) { + // temp, until BE not sent the triangle button + for (var i = 0; i < nodeVisualElements.length; i++) { + if (nodeVisualElements[i].type === 'button' && nodeVisualElements[i].name === 'icon_triangle_warning') { + nodeVisualElements.splice(i, 1); + return; + } + } + } } return nodeVisualElements; } diff --git a/src/generic-components/graph/NodeVisualElementConstants.js b/src/generic-components/graph/NodeVisualElementConstants.js index 11d9f7d..aeeedf7 100644 --- a/src/generic-components/graph/NodeVisualElementConstants.js +++ b/src/generic-components/graph/NodeVisualElementConstants.js @@ -1,25 +1,28 @@ /* - * ============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. */ + export default { SVG_CIRCLE: 'circle', SVG_LINE: 'line', @@ -41,6 +44,5 @@ export default { ICON_ELLIPSES: 'icon_ellipses', ICON_TRIANGLE_WARNING: 'icon_triangle_warning', ICON_TICK: 'icon_tick', - ICON_WARNING: 'icon_warning', - BUTTON_CLICK_NODE_DETAILS: 'NODE_DETAILS' + ICON_WARNING: 'icon_warning' }; diff --git a/src/generic-components/graph/TempCreateAttributes.js b/src/generic-components/graph/TempCreateAttributes.js new file mode 100644 index 0000000..fac32ba --- /dev/null +++ b/src/generic-components/graph/TempCreateAttributes.js @@ -0,0 +1,464 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import React from 'react'; + + +export default { + createNodeAttributes: () => { + return { + className: 'node' + }; + }, + createShapeAttributes: () => { + return { + r: 3 + }; + }, + createCircleStyle: () => { + return { + fill: 'rgb(98, 102, 104)', + stroke: 'rgb(78, 82, 84)', + strokeWidth: 1 + }; + }, + createLinkAttributes: () => { + return { + className: 'link', + x1: 50, + y1: 50, + x2: 100, + y2: 500, + }; + }, + createLineStyle: () => { + return { + stroke: 'rgb(217, 218, 218)', + strokeWidth: 1 + }; + }, + createTestCircle: () => { + return React.createElement('circle', { + cx: '100', + cy: '100', + r: '15', + fill: 'rgb(255, 255, 255)', + stroke: 'rgb(98, 102, 104)', + strokeWidth: '3' + }); + }, + getNodeLinkArray: () => { + return { + 'graphMeta': { + 'aaiEntityNodeDescriptors': { + 'generalNodeClass': { + 'class': 'aai-entity-node general-node', + 'visualElements': [ + { + 'type': 'circle', + 'class': 'outer', + 'svgAttributes': { + 'r': '16' + } + }, + { + 'type': 'circle', + 'class': 'inner', + 'svgAttributes': { + 'r': '10' + } + }, + { + 'type': 'text', + 'class': 'id-type-label', + 'displayKey': 'itemType', + 'shapeAttributes': { + 'offset': { + 'x': '0', + 'y': '33' + } + } + }, + { + 'type': 'text', + 'class': 'id-value-label', + 'displayKey': 'itemNameValue', + 'shapeAttributes': { + 'offset': { + 'x': '0', + 'y': '48' + } + } + } + ] + }, + 'searchedNodeClass': { + 'class': 'aai-entity-node search-node', + 'visualElements': [ + { + 'type': 'circle', + 'class': 'outer', + 'svgAttributes': { + 'r': '16' + } + }, + { + 'type': 'circle', + 'class': 'inner', + 'svgAttributes': { + 'r': '10' + } + }, + { + 'type': 'text', + 'class': 'id-type-label', + 'displayKey': 'itemType', + 'shapeAttributes': { + 'offset': { + 'x': '0', + 'y': '33' + } + } + }, + { + 'type': 'text', + 'class': 'id-value-label', + 'displayKey': 'itemNameValue', + 'shapeAttributes': { + 'offset': { + 'x': '0', + 'y': '48' + } + } + } + ] + }, + 'selectedSearchedNodeClass': { + 'class': 'aai-entity-node selected-search-node', + 'visualElements': [ + { + 'type': 'circle', + 'class': 'outer', + 'svgAttributes': { + 'r': '31' + } + }, + { + 'type': 'circle', + 'class': 'inner', + 'svgAttributes': { + 'r': '20' + } + }, + { + 'type': 'text', + 'class': 'id-type-label', + 'displayKey': 'itemType', + 'shapeAttributes': { + 'offset': { + 'x': '0', + 'y': '48' + } + } + }, + { + 'type': 'text', + 'class': 'id-value-label', + 'displayKey': 'itemNameValue', + 'shapeAttributes': { + 'offset': { + 'x': '0', + 'y': '63' + } + } + }, + { + 'type': 'button', + 'name': 'icon_ellipses', + 'class': 'node-button', + 'shapeAttributes': { + 'offset': { + 'x': '33', + 'y': '-35' + } + }, + 'svgAttributes': { + 'className': 'node-button', + 'r': '10' + } + }, + { + 'type': 'button', + 'name': 'icon_triangle_warning', + 'class': 'node-button', + 'shapeAttributes': { + 'offset': { + 'x': '46', + 'y': '-12' + } + }, + 'svgAttributes': { + 'className': 'node-button', + 'r': '10' + } + } + ] + }, + 'selectedNodeClass': { + 'class': 'aai-entity-node selected-node', + 'visualElements': [ + { + 'type': 'circle', + 'class': 'outer', + 'svgAttributes': { + 'r': '31' + } + }, + { + 'type': 'circle', + 'class': 'inner', + 'svgAttributes': { + 'r': '20' + } + }, + { + 'type': 'text', + 'class': 'id-type-label', + 'displayKey': 'itemType', + 'shapeAttributes': { + 'offset': { + 'x': '0', + 'y': '48' + } + } + }, + { + 'type': 'text', + 'class': 'id-value-label', + 'displayKey': 'itemNameValue', + 'shapeAttributes': { + 'offset': { + 'x': '0', + 'y': '63' + } + } + }, + { + 'type': 'button', + 'name': 'icon_ellipses', + 'class': 'node-button', + 'shapeAttributes': { + 'offset': { + 'x': '33', + 'y': '-35' + } + }, + 'svgAttributes': { + 'className': 'node-button', + 'r': '10' + } + }, + { + 'type': 'button', + 'name': 'icon_triangle_warning', + 'class': 'node-button', + 'shapeAttributes': { + 'offset': { + 'x': '46', + 'y': '-12' + } + }, + 'svgAttributes': { + 'className': 'node-button', + 'r': '10' + } + } + ] + } + }, + 'numNodes': 6, + 'numLinks': 5, + 'renderTimeInMs': 4550, + 'numLinksResolvedSuccessfullyFromCache': 0, + 'numLinksResolvedSuccessfullyFromServer': 7, + 'numLinkResolveFailed': 0 + }, + 'nodes': [{ + 'id': 'TRINITY-PSERVER', + 'itemType': 'pserver', + 'itemNameKey': 'pserver.TRINITY-PSERVER', + 'itemNameValue': 'TRINITY-PSERVER', + 'itemProperties': { + 'hostname': 'TRINITY-PSERVER', + 'in-maint': 'false', + 'resource-version': '1455590484' + }, + 'nodeMeta': { + 'className': 'selectedSearchedNodeClass', + 'nodeDebug': null, + 'selfLinkResponseTimeInMs': 628, + 'relationshipNode': false, + 'searchTarget': true, + 'enrichableNode': false, + 'nodeValidated': true, + 'nodeIssue': true + } + }, { + 'id': 'TRINITYSIL', + 'itemType': 'complex', + 'itemNameKey': 'complex.TRINITYSIL', + 'itemNameValue': 'TRINITYSIL', + 'itemProperties': { + 'country': 'USA', + 'postal-code': '07748', + 'city': 'Middletown', + 'physical-location-id': 'TRINITYSIL', + 'resource-version': '1459957457', + 'street1': 'Trinity', + 'state': 'NJ', + 'physical-location-type': 'Trinity', + 'region': 'US' + }, + 'nodeMeta': { + 'className': 'generalNodeClass', + 'nodeDebug': null, + 'selfLinkResponseTimeInMs': 644, + 'relationshipNode': false, + 'searchTarget': false, + 'enrichableNode': false, + 'nodeValidated': true, + 'nodeIssue': false + } + }, { + 'id': 'c385bb3e-6ebd-4898-bc92-792e0ac2db50', + 'itemType': 'vserver', + 'itemNameKey': 'vserver.c385bb3e-6ebd-4898-bc92-792e0ac2db50', + 'itemNameValue': 'c385bb3e-6ebd-4898-bc92-792e0ac2db50', + 'itemProperties': { + 'in-maint': 'false', + 'resource-version': '1475160142', + 'vserver-name': 'bems0001vm001', + 'prov-status': 'ACTIVE', + 'vserver-id': 'c385bb3e-6ebd-4898-bc92-792e0ac2db50', + 'vserver-name2': 'bems0001vm001bem001-1452', + 'vserver-selflink': 'TRINITY vserverLink', + 'is-closed-loop-disabled': 'false' + }, + 'nodeMeta': { + 'className': 'generalNodeClass', + 'nodeDebug': null, + 'selfLinkResponseTimeInMs': 2633, + 'relationshipNode': false, + 'searchTarget': false, + 'enrichableNode': false + } + }, { + 'id': '7c73d776-001d-4042-a958-37f2e419ed10', + 'itemType': 'vserver', + 'itemNameKey': 'vserver.7c73d776-001d-4042-a958-37f2e419ed10', + 'itemNameValue': '7c73d776-001d-4042-a958-37f2e419ed10', + 'itemProperties': { + 'resource-version': '1477075390', + 'vserver-name': 'nsbg0001vm002', + 'prov-status': 'NVTPROV', + 'vserver-id': '7c73d776-001d-4042-a958-37f2e419ed10', + 'vserver-name2': 'VM-19631', + 'vserver-selflink': 'TRINITY vserverLink' + }, + 'nodeMeta': { + 'className': 'generalNodeClass', + 'nodeDebug': null, + 'selfLinkResponseTimeInMs': 2368, + 'relationshipNode': false, + 'searchTarget': false, + 'enrichableNode': false + } + }, { + 'id': 'fc6be93d-915e-4034-a8f9-463b70130614', + 'itemType': 'vserver', + 'itemNameKey': 'vserver.fc6be93d-915e-4034-a8f9-463b70130614', + 'itemNameValue': 'fc6be93d-915e-4034-a8f9-463b70130614', + 'itemProperties': { + 'resource-version': '1477075398', + 'vserver-name': 'nsbg0001vm004', + 'prov-status': 'NVTPROV', + 'vserver-id': 'fc6be93d-915e-4034-a8f9-463b70130614', + 'vserver-name2': 'VM-19630', + 'vserver-selflink': 'TRINITY vserverLink' + }, + 'nodeMeta': { + 'className': 'generalNodeClass', + 'nodeDebug': null, + 'selfLinkResponseTimeInMs': 2621, + 'relationshipNode': false, + 'searchTarget': false, + 'enrichableNode': false + } + }, { + 'id': '8555c2ed-6818-43c5-8cf5-cd36b0169031', + 'itemType': 'vserver', + 'itemNameKey': 'vserver.8555c2ed-6818-43c5-8cf5-cd36b0169031', + 'itemNameValue': '8555c2ed-6818-43c5-8cf5-cd36b0169031', + 'itemProperties': { + 'resource-version': '1477075396', + 'vserver-name': 'nsbg0001vm003', + 'prov-status': 'NVTPROV', + 'vserver-id': '8555c2ed-6818-43c5-8cf5-cd36b0169031', + 'vserver-name2': 'VM-19629', + 'vserver-selflink': 'TRINITY vserverLink' + }, + 'nodeMeta': { + 'className': 'generalNodeClass', + 'nodeDebug': null, + 'selfLinkResponseTimeInMs': 2663, + 'relationshipNode': false, + 'searchTarget': false, + 'enrichableNode': false + } + }], + 'links': [{ + 'id': 'TRINITY-PSERVER_TRINITYSIL', + 'source': 'TRINITY-PSERVER', + 'target': 'TRINITYSIL' + }, { + 'id': 'TRINITY-PSERVER_c385bb3e-6ebd-4898-bc92-792e0ac2db50', + 'source': 'TRINITY-PSERVER', + 'target': 'c385bb3e-6ebd-4898-bc92-792e0ac2db50' + }, { + 'id': 'TRINITY-PSERVER_7c73d776-001d-4042-a958-37f2e419ed10', + 'source': 'TRINITY-PSERVER', + 'target': '7c73d776-001d-4042-a958-37f2e419ed10' + }, { + 'id': 'TRINITY-PSERVER_fc6be93d-915e-4034-a8f9-463b70130614', + 'source': 'TRINITY-PSERVER', + 'target': 'fc6be93d-915e-4034-a8f9-463b70130614' + }, { + 'id': 'TRINITY-PSERVER_8555c2ed-6818-43c5-8cf5-cd36b0169031', + 'source': 'TRINITY-PSERVER', + 'target': '8555c2ed-6818-43c5-8cf5-cd36b0169031' + }] + }; + } +}; diff --git a/src/generic-components/treeNode/TreeNode.jsx b/src/generic-components/treeNode/TreeNode.jsx new file mode 100644 index 0000000..b5fc3cc --- /dev/null +++ b/src/generic-components/treeNode/TreeNode.jsx @@ -0,0 +1,79 @@ +/* + * ============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 + * + * 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===================================================== + * + * ECOMP and OpenECOMP are trademarks + * and service marks of AT&T Intellectual Property. + */ + +import React, {Component} from 'react'; +import classNames from 'classnames'; + + + + +class TreeNode extends Component { + + + constructor(props) { + super(props); + this.state = { + visible: false, + }; + } + + toggle = () => { + this.setState({visible: !this.state.visible}); + }; + + render() { + var childNodes; + var classObj; + if (this.props.node !== undefined && this.props.node.childNodes !== undefined) { + childNodes = this.props.node.childNodes.map(function (node, index) { + return <li key={index}><TreeNode node={node}/></li>; + }); + + classObj = { + togglable: true, + 'togglable-down': this.state.visible, + 'togglable-up': !this.state.visible + }; + } + + var style; + if (!this.state.visible) { + style = {display: 'none'}; + } + + return ( + <div> + <h7 onClick={this.toggle} className={classNames(classObj)}> + {this.props.node.title} + </h7> + <ul style={style} className='node-tree'> + {childNodes} + </ul> + </div> + ); + } +} + +export default TreeNode; diff --git a/src/index.html b/src/index.html index 79775df..7af14ec 100644 --- a/src/index.html +++ b/src/index.html @@ -1,31 +1,8 @@ -<!-- - - ============LICENSE_START======================================================= - org.onap.aai - ================================================================================ - Copyright © 2017 AT&T Intellectual Property. All rights reserved. - Copyright © 2017 Amdocs - ================================================================================ - 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 - - 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========================================================= - - ECOMP is a trademark and service mark of AT&T Intellectual Property. - ---> <html> <head> <meta charset="utf-8"> <title>A&AI UI</title> + <link rel="stylesheet" href="https://unpkg.com/react-select/dist/react-select.css"> </head> <body> diff --git a/src/utils/Crypto.js b/src/utils/Crypto.js new file mode 100644 index 0000000..c2b34a0 --- /dev/null +++ b/src/utils/Crypto.js @@ -0,0 +1,22 @@ +/** + * Created by salmaat on 7/13/2017. + */ +import CryptoJS from 'crypto-js'; + +var key = 'key2017'; + +function encrypt(text) { + var encrypted = CryptoJS.AES.encrypt(text, key); + return encrypted.toString().split('/').join('*'); +} + +function decrypt(text) { + var decrypted = CryptoJS.AES.decrypt(text.split('*').join('/'), key); + return decrypted.toString(CryptoJS.enc.Utf8); +} + + +module.exports = { + encrypt: encrypt, + decrypt: decrypt +}; diff --git a/src/utils/DateTimeChartUtil.js b/src/utils/DateTimeChartUtil.js index f0735e5..44224a3 100644 --- a/src/utils/DateTimeChartUtil.js +++ b/src/utils/DateTimeChartUtil.js @@ -1,25 +1,28 @@ /* - * ============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. */ + let moment = require('moment'); let d3Scale = require('d3-scale'); let d3Time = require('d3-time'); @@ -33,6 +36,14 @@ export function dateFormatLocalTimeZoneMMDDYYYY(time) { }; /** + * Converts specified time (ms since epoc) into a + * YYYY-MM-DD format for the local timezone + */ +export function dateFormatLocalTimeZoneYYYYMMDD(time) { + return moment(time).format('YYYY-MM-DD'); +}; + +/** * Build a map of 'ticks' to be used on a graph axis based on the date range * identified by the specified JSON attribute (ticks will be on a daily basis) * @param data - the array of JSON data @@ -44,12 +55,12 @@ export function getTicks(data, attrKey) { if (!data || !data.length) { return []; } - + const domain = [new Date(data[0][attrKey]), new Date(data[data.length - 1][attrKey])]; const scale = d3Scale.scaleTime().domain(domain).range([0, 1]); const ticks = scale.ticks(d3Time.timeDay, 1); - + return ticks.map(entry => +entry); }; @@ -64,7 +75,7 @@ export function getTicksData(data, ticks, attrKey) { if (!data || !data.length) { return []; } - + const dataMap = new Map(data.map((i) => [i[attrKey], i])); ticks.forEach(function (item) { if (!dataMap.has(item)) { diff --git a/src/utils/Routes.js b/src/utils/Routes.js index 9d15177..5a5e089 100644 --- a/src/utils/Routes.js +++ b/src/utils/Routes.js @@ -1,36 +1,94 @@ -/* - * ============LICENSE_START======================================================= - * org.onap.aai - * ================================================================================ - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * ================================================================================ - * 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 - * - * 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========================================================= - * - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ +import {encrypt } from './Crypto.js'; +import { decrypt } from '../utils/Crypto.js'; + + export function changeUrlAddress(pathObj, historyObj) { - let toGo = '/' + - pathObj.route + - '/' + - pathObj.hashId; + let toGo = '/' + pathObj.route; + // left global search to act the same as before for our 2 static views for now + // until we decide to change those 2 views too to act like extensible views. + if (pathObj.route === 'schema' || pathObj.route === 'vnfSearch') { + if (pathObj.filterValues && pathObj.filterValues.length > 0) { + let filterList = []; + for (let index in pathObj.filterValues) { + if (pathObj.filterValues[index].filterValue !== undefined) { + filterList.push(pathObj.filterValues[index].filterId + + '=' + + pathObj.filterValues[index].filterValue); + } else { + filterList.push(pathObj.filterValues[index].filterId + '='); + } + } + toGo = toGo + '/' + filterList.toString(); + } else { + toGo = toGo + '/' + pathObj.hashId; + } + } else { + toGo += '/' + encrypt(JSON.stringify(pathObj)); + } historyObj.push(toGo, {lastRoute: pathObj.route}); } -export function buildRouteObj(routePath, routeHash) { +export function buildRouteObjWithHash(routePath, routeHash) { return { route: routePath, hashId: routeHash }; } + + +export function decryptParamsForView(params) { + let jsonParam = {}; + + function isJson(str) { + try { + JSON.parse(str); + } catch (e) { + return false; + } + return true; + }; + + let stringParams; + + try { + stringParams = decrypt(params); + } catch(e) { + //add inline message in next story + //happens when user changes the url. + } + + if(!isJson(stringParams)) { + return jsonParam; + } + + jsonParam = JSON.parse(stringParams); + return jsonParam; +} + +export function buildRouteObjWithFilters(routePath, routeFiltersObj) { + let filterValues = []; + if (routeFiltersObj !== undefined) { + for (let id in routeFiltersObj) { + if (routeFiltersObj[id] !== undefined) { + filterValues.push( + { + 'filterId': id, + 'filterValue': routeFiltersObj[id] + } + ); + } else { + filterValues.push( + { + 'filterId': id, + 'filterValue': '' + } + ); + } + } + } + + return { + route: routePath, + filterValues: filterValues + }; +} |