diff options
Diffstat (limited to 'src/app')
39 files changed, 3561 insertions, 0 deletions
diff --git a/src/app/AppStore.js b/src/app/AppStore.js new file mode 100644 index 0000000..0cdef4c --- /dev/null +++ b/src/app/AppStore.js @@ -0,0 +1,60 @@ +/* + * ============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 GlobalAutoCompleteSearchBarReducer from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarReducer.js'; +import TierSupportReducer from 'app/tierSupport/TierSupportReducer.js'; +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'; + +function createCompose() { + return window.devToolsExtension + ? + compose(applyMiddleware(thunkMiddleware), window.devToolsExtension()) + : applyMiddleware(thunkMiddleware); +} + +export const storeCreator = (initialState) => createStore( + combineReducers({ + mainWrapper: MainScreenWrapperReducer, + globalAutoCompleteSearchBarReducer: GlobalAutoCompleteSearchBarReducer, + tierSupport: TierSupportReducer, + inventoryReducer: InventoryReducer, + dynamicViewReducer: DynamicViewLoaderReducer, + vnfSearch: VnfSearchReducer, + globalInlineMessageBar: GlobalInlineMessageBarReducer + }), + initialState, + createCompose() +); + + +const store = storeCreator(); + +export default store; diff --git a/src/app/Application.jsx b/src/app/Application.jsx new file mode 100644 index 0000000..39adca8 --- /dev/null +++ b/src/app/Application.jsx @@ -0,0 +1,43 @@ +/* + * ============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 './AppStore.js'; + + +class Application extends Component { + + render() { + return ( + <Provider store={store}> + {this.props.children} + </Provider> + ); + } +} + +export default Application; + diff --git a/src/app/GlobalInlineMessageBar/GlobalInlineMessageBar.jsx b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBar.jsx new file mode 100644 index 0000000..854553a --- /dev/null +++ b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBar.jsx @@ -0,0 +1,57 @@ +/* + * ============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 {connect} from 'react-redux'; +import React, {Component} from 'react'; + +import InlineMessage from 'generic-components/InlineMessage/InlineMessage.jsx'; + +let mapStateToProps = ({globalInlineMessageBar}) => { + let { + feedbackMsgText = '', + feedbackMsgSeverity = '' + } = globalInlineMessageBar; + + return { + feedbackMsgText, + feedbackMsgSeverity + }; +}; + +export class GlobalInlineMessageBar extends Component { + static propTypes = { + feedbackMsgText: React.PropTypes.string, + feedbackMsgSeverity: React.PropTypes.string + }; + + render() { + let {feedbackMsgSeverity, feedbackMsgText} = this.props; + + return ( + <InlineMessage level={feedbackMsgSeverity} messageTxt={feedbackMsgText}/> + ); + } +} +export default connect(mapStateToProps)(GlobalInlineMessageBar); + diff --git a/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js new file mode 100644 index 0000000..1cdda0e --- /dev/null +++ b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js @@ -0,0 +1,43 @@ +/* + * ============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 { + globalInlineMessageBarActionTypes +} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarConstants.js'; + +export function getSetGlobalMessageEvent(msgText, msgSeverity) { + return { + type: globalInlineMessageBarActionTypes.SET_GLOBAL_MESSAGE, + data: { + msgText: msgText, + msgSeverity: msgSeverity + } + }; +} + +export function getClearGlobalMessageEvent() { + return { + type: globalInlineMessageBarActionTypes.CLEAR_GLOBAL_MESSAGE + }; +} diff --git a/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarConstants.js b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarConstants.js new file mode 100644 index 0000000..8d56945 --- /dev/null +++ b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarConstants.js @@ -0,0 +1,30 @@ +/* + * ============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'; + +export const globalInlineMessageBarActionTypes = keyMirror({ + SET_GLOBAL_MESSAGE: null, + CLEAR_GLOBAL_MESSAGE: null +}); diff --git a/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarReducer.js b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarReducer.js new file mode 100644 index 0000000..1e65605 --- /dev/null +++ b/src/app/GlobalInlineMessageBar/GlobalInlineMessageBarReducer.js @@ -0,0 +1,45 @@ +/* + * ============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 { + globalInlineMessageBarActionTypes +} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarConstants.js'; + +export default (state = {}, action) => { + switch (action.type) { + case globalInlineMessageBarActionTypes.SET_GLOBAL_MESSAGE: + return { + ...state, + feedbackMsgText: action.data.msgText, + feedbackMsgSeverity: action.data.msgSeverity + }; + case globalInlineMessageBarActionTypes.CLEAR_GLOBAL_MESSAGE: + return { + ...state, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + } + return state; +}; diff --git a/src/app/MainScreenHeader.jsx b/src/app/MainScreenHeader.jsx new file mode 100644 index 0000000..a7fc1f1 --- /dev/null +++ b/src/app/MainScreenHeader.jsx @@ -0,0 +1,196 @@ +/* + * ============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 FontAwesome from 'react-fontawesome'; +import Button from 'react-bootstrap/lib/Button.js'; +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 { + Route, + NavLink +} from 'react-router-dom'; + +import { + AAI_TITLE, + MENU_ITEM_TIER_SUPPORT, + MENU_ITEM_VNF_SEARCH +} from './MainScreenWrapperConstants.js'; + +import { + showMainMenu +} from './MainScreenWrapperActionHelper.js'; + +import {clearSuggestionsTextField} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js'; + +import customViews from 'resources/views/customViews.json'; + +const mapStateToProps = ({mainWrapper}) => { + let { + showMenu = false, + toggleButtonActive = false + } = mainWrapper; + + return { + showMenu, + toggleButtonActive + }; +}; + +const mapActionsToProps = (dispatch) => { + return { + onShowMenu: () => dispatch(showMainMenu(true)), + onHideMenu: () => { + dispatch(showMainMenu(false)); + }, + dispatchAnalyticsData: () => dispatch( + postAnalyticsData(document.documentElement.outerHTML.replace('\s+', ''))), + onRouteChange: () => { + dispatch(getClearGlobalMessageEvent()); + dispatch(clearSuggestionsTextField()); + } + }; +}; + +class MainScreenHeader extends Component { + static propTypes = { + showMenu: React.PropTypes.bool, + toggleButtonActive: React.PropTypes.bool + }; + + navigationLinkAndCurrentPathMatch(location, to) { + let linkPathElements = to.split('/'); + let locationElements = location.pathname.split('/'); + + // the element arrays above will have the route at index 1 ... need to + // verify if the routes match + return locationElements[1] === linkPathElements[1]; + } + + hasRouteChanged(currentPath, nextPath) { + let currentPathParts = currentPath.split('/'); + let nextPathParts = nextPath.split('/'); + + if (currentPathParts[1] !== nextPathParts[1]) { + return true; + } else { + return false; + } + } + + componentWillReceiveProps(nextProps) { + if (this.props.location && + this.props.location.pathname !== nextProps.location.pathname) { + // update analytics + this.props.dispatchAnalyticsData(); + + if (this.hasRouteChanged(this.props.location.pathname, + nextProps.location.pathname)) { + this.props.onRouteChange(); + } + } + } + + render() { + let { + showMenu, + onShowMenu, + onHideMenu, + toggleButtonActive + } = this.props; + + let menuOptions = []; + + const MenuItem = ({label, iconClass, to}) => ( + <Route path={to} children={({location}) => ( + <NavLink to={to} onClick={onHideMenu}> + <div className={this.navigationLinkAndCurrentPathMatch(location, to) ? 'main-menu-button-active' : 'main-menu-button'}> + <div className={iconClass}/> + <div className='button-icon'>{label}</div> + </div> + </NavLink> + )}/> + ); + + // add Tier Support view + menuOptions.push( + <MenuItem to='/viewInspect' 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' + label={MENU_ITEM_VNF_SEARCH} + iconClass='button-icon vnf-search-button-icon'/> + ); + + // add all custom view menu options + for (let view in customViews) { + menuOptions.push( + <MenuItem to={customViews[view]['viewName']} + label={customViews[view]['displayName']} + iconClass='button-icon inventory-button-icon'/> + ); + } + + 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> + </div> + + ); + } +} + +export default connect(mapStateToProps, mapActionsToProps)(MainScreenHeader); diff --git a/src/app/MainScreenWrapper.jsx b/src/app/MainScreenWrapper.jsx new file mode 100644 index 0000000..ba2a0e9 --- /dev/null +++ b/src/app/MainScreenWrapper.jsx @@ -0,0 +1,103 @@ +/* + * ============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 TierSupport from './tierSupport/TierSupport.jsx'; +import VnfSearch from './vnfSearch/VnfSearch.jsx'; +import MainScreenHeader from './MainScreenHeader.jsx'; + +import DynamicViewLoader from + 'generic-components/dynamicViewLoader/dynamicViewLoader.jsx'; + +import { + Route, + HashRouter as Router, + Switch, + Redirect +} from 'react-router-dom'; + +import { + windowResize +} from './MainScreenWrapperActionHelper.js'; + +import customViews from 'resources/views/customViews.json'; + +const mapStateToProps = ({mainWrapper}) => { + let { + showMenu = false, + toggleButtonActive = false + } = mainWrapper; + + return { + showMenu, + toggleButtonActive + }; +}; + +const mapActionsToProps = (dispatch) => { + return { + onWindowSizeChange: () => dispatch(windowResize()) + }; +}; + +class MainScreenWrapper extends Component { + + constructor() { + super(); + window.addEventListener('resize', () => { + this.props.onWindowSizeChange(); + }); + } + + render() { + let customViewList = []; + + // add all custom views + for (let view in customViews) { + customViewList.push( + <Route path={'/' + customViews[view]['viewName']} + component={DynamicViewLoader}/> + ); + } + + return ( + <Router> + <div> + <Switch> + <Redirect from='/' exact to='/viewInspect'/> + </Switch> + <Route path='/' component={MainScreenHeader}/> + <Route path='/viewInspect/:viParam?' component={TierSupport}/> + <Route path='/vnfSearch/:vnfParam?' component={VnfSearch}/> + {customViewList} + </div> + </Router> + ); + } +} + +export default connect(mapStateToProps, mapActionsToProps)(MainScreenWrapper); diff --git a/src/app/MainScreenWrapperActionHelper.js b/src/app/MainScreenWrapperActionHelper.js new file mode 100644 index 0000000..86f1196 --- /dev/null +++ b/src/app/MainScreenWrapperActionHelper.js @@ -0,0 +1,53 @@ +/* + * ============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 {aaiActionTypes} from './MainScreenWrapperConstants.js'; + +function createWindowSizeChangeEvent() { + return { + type: aaiActionTypes.AAI_WINDOW_RESIZE + }; +} + +function createShowMenuEvent(show) { + return { + type: aaiActionTypes.AAI_SHOW_MENU, + data: { + showMenu: show + } + }; +} + +export function windowResize() { + return dispatch => { + dispatch(createWindowSizeChangeEvent()); + }; +} + +export function showMainMenu(show) { + return dispatch => { + dispatch(createShowMenuEvent(show)); + }; +} diff --git a/src/app/MainScreenWrapperConstants.js b/src/app/MainScreenWrapperConstants.js new file mode 100644 index 0000000..038b197 --- /dev/null +++ b/src/app/MainScreenWrapperConstants.js @@ -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 keyMirror from 'utils/KeyMirror.js'; + +export const aaiActionTypes = keyMirror({ + SET_CURRENT_SCREEN: null, + AAI_WINDOW_RESIZE: null, + AAI_SHOW_MENU: null +}); + +export const screens = keyMirror({ + TIER_SUPPORT: null, + INVENTORY: null, + VNF_SEARCH: null +}); + +export const AAI_TITLE = 'A&AI'; +export const MENU_ITEM_TIER_SUPPORT = 'View & Inspect'; +export const MENU_ITEM_VNF_SEARCH = 'VNFs'; diff --git a/src/app/MainScreenWrapperReducer.js b/src/app/MainScreenWrapperReducer.js new file mode 100644 index 0000000..c112316 --- /dev/null +++ b/src/app/MainScreenWrapperReducer.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. + */ + +import {aaiActionTypes} from './MainScreenWrapperConstants.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 + // is active + }; + } + return state; +}; + diff --git a/src/app/analytics/AnalyticsActions.js b/src/app/analytics/AnalyticsActions.js new file mode 100644 index 0000000..ddfbde7 --- /dev/null +++ b/src/app/analytics/AnalyticsActions.js @@ -0,0 +1,54 @@ +/* + * ============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 {ANALYTICS_URL} from 'app/analytics/AnalyticsConstants.js'; +let fetch = require('node-fetch'); + + +function getAnalyticsPostBody(payload){ + return { + page: '', + function: '', + action : payload + }; +} + +export function postAnalyticsData(payload){ + + return () => { + fetch(ANALYTICS_URL, { + method: POST, + headers: POST_HEADER, + body: JSON.stringify(getAnalyticsPostBody(payload)) + }); + + }; + +} + diff --git a/src/app/analytics/AnalyticsConstants.js b/src/app/analytics/AnalyticsConstants.js new file mode 100644 index 0000000..1fa5c3c --- /dev/null +++ b/src/app/analytics/AnalyticsConstants.js @@ -0,0 +1,27 @@ +/* + * ============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 {BASE_URL} from 'app/networking/NetworkConstants.js'; + +export const ANALYTICS_URL = BASE_URL + '/api/v2/storeAnalytics'; diff --git a/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx new file mode 100644 index 0000000..92f74bc --- /dev/null +++ b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx @@ -0,0 +1,105 @@ +/* + * ============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 {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 { + queryRequestedValues, + clearSuggestionsTextField, + onSuggestionsChange, + onSuggestionsClearRequested, + getInvalidSearchInputEvent, + setNotificationText +} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js'; + +let mapActionToProps = (dispatch) => { + return { + onSuggestionsFetchRequested: ({value}) => dispatch( + queryRequestedValues(value)), + onClearSuggestionsTextFieldRequested: () => { + dispatch(getClearGlobalMessageEvent()); + dispatch(clearSuggestionsTextField()); + }, + onInputChange: (event, {newValue}) => { + dispatch(getClearGlobalMessageEvent()); + dispatch(onSuggestionsChange(event, newValue)); + }, + onSuggestionsClearRequested: () => dispatch(onSuggestionsClearRequested()), + dispatchAnalytics: () => dispatch( + postAnalyticsData(document.documentElement.outerHTML.replace('\s+', ''))), + onInvalidSearch: (searchText) => { + dispatch(getInvalidSearchInputEvent(searchText)); + }, + onMessageStateChange: (msgText, msgSeverity) => { + dispatch(setNotificationText(msgText, msgSeverity)); + } + }; +}; + +let mapStateToProps = ({globalAutoCompleteSearchBarReducer}) => { + let { + value = '', + suggestions = [], + cachedSuggestions = [], + suggestionName = 'text', + clearSearchText = false, + feedbackMsgText = '', + feedbackMsgSeverity = '' + } = globalAutoCompleteSearchBarReducer; + + return { + value, + suggestions, + cachedSuggestions, + suggestionName, + clearSearchText, + feedbackMsgText, + feedbackMsgSeverity + }; +}; + +export class GlobalAutoCompleteSearchBar extends Component { + componentWillReceiveProps(nextProps) { + if (nextProps.clearSearchText) { + this.props.onClearSuggestionsTextFieldRequested(); + } + + if (nextProps.feedbackMsgText !== this.props.feedbackMsgText) { + this.props.onMessageStateChange(nextProps.feedbackMsgText, + nextProps.feedbackMsgSeverity); + } + } + + render() { + return ( + <AutoCompleteSearchBar {...this.props} /> + ); + } +} +export default connect(mapStateToProps, mapActionToProps)( + GlobalAutoCompleteSearchBar); diff --git a/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js new file mode 100644 index 0000000..4ef684d --- /dev/null +++ b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js @@ -0,0 +1,176 @@ +/* + * ============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 {getTSUIElasticSearchQueryString} from 'app/networking/NetworkUtil.js'; +import networkCall from 'app/networking/NetworkCalls.js'; +import { + POST, + POST_HEADER, + ERROR_RETRIEVING_DATA +} from 'app/networking/NetworkConstants.js'; + +import { + globalAutoCompleteSearchBarActionTypes, + ERROR_INVALID_SEARCH_TERMS, + GLOBAL_SEARCH_URL +} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js'; +import { + getSetGlobalMessageEvent, + getClearGlobalMessageEvent +} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js'; + + +function createSuggestionFoundEvent({suggestions}) { + return { + type: globalAutoCompleteSearchBarActionTypes.SUGGESTION_FOUND, + data: {suggestions} + }; +} + +function createSuggestionNotFoundEvent() { + return { + type: globalAutoCompleteSearchBarActionTypes.SUGGESTION_NOT_FOUND + }; +} + +function createSuggestionChangedEvent(value) { + return { + type: globalAutoCompleteSearchBarActionTypes.SUGGESTION_CHANGED, + data: value + }; +} + +function getInvalidQueryEvent(value) { + return { + type: globalAutoCompleteSearchBarActionTypes.NETWORK_ERROR, + data: {value: value, errorMsg: ERROR_RETRIEVING_DATA} + }; +} + +function getSearchBarWarningMessageEvent(message) { + return { + type: globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT, + data: {errorMsg: message} + }; +} +export function getInvalidSearchInputEvent(value) { + return getSearchBarWarningMessageEvent( + ERROR_INVALID_SEARCH_TERMS + ': ' + value); +} + + +function fetchView(selectedSuggestion) { + return { + type: globalAutoCompleteSearchBarActionTypes.SUGGESTION_CLICKED, + data: {selectedSuggestion: selectedSuggestion} + }; +} + + +export function populateView( + searchRequestObject, keyWord, selectedNodeFetchRequest) { + if (selectedNodeFetchRequest === undefined) { + let postBody = JSON.stringify(searchRequestObject); + selectedNodeFetchRequest = + () => networkCall.fetchRequest('', POST, + POST_HEADER, postBody); + } + + return dispatch => { + dispatch(fetchView(searchRequestObject)); + }; +} + + +export function fetchRequestedValues(fetchRequestCallback, keyWord) { + return dispatch => { + return fetchRequestCallback().then( + (responseJson) => responseJson.suggestions + ).then( + (filteredResults)=> { + if (filteredResults.length > 0) { + dispatch(createSuggestionFoundEvent({suggestions: filteredResults})); + } else { + dispatch(createSuggestionNotFoundEvent()); + } + } + ).catch( + () => { + dispatch(getInvalidQueryEvent(keyWord)); + } + ); + }; +} + +export function queryRequestedValues(keyWord, requestedFetchRequest) { + if (requestedFetchRequest === undefined) { + let postBody = JSON.stringify(getTSUIElasticSearchQueryString(keyWord)); + requestedFetchRequest = + () => networkCall.fetchRequest(GLOBAL_SEARCH_URL, POST, POST_HEADER, + postBody); + } + return dispatch => { + dispatch(fetchRequestedValues(requestedFetchRequest, keyWord), keyWord); + }; +} + +export function clearSuggestionsTextField() { + return dispatch => { + dispatch( + {type: globalAutoCompleteSearchBarActionTypes.CLEAR_SUGGESTIONS_TEXT_FIELD}); + }; +} + +export function onSuggestionsChange(event, value) { + return dispatch => { + dispatch(createSuggestionChangedEvent(value)); + //Only fetch values if the enter key is used. + if (event.keyCode === 13) { + let postBody = JSON.stringify(getTSUIElasticSearchQueryString(value)); + dispatch(fetchRequestedValues( + () => networkCall.fetchRequest(GLOBAL_SEARCH_URL, POST, POST_HEADER, + postBody), value)); + } + }; +} + +export function onSuggestionsClearRequested() { + return dispatch => { + dispatch({type: globalAutoCompleteSearchBarActionTypes.CLEAR_SUGGESTIONS}); + }; +} + +export function setNotificationText(msgText, msgSeverity) { + if (msgText.length > 0) { + return dispatch => { + dispatch( + getSetGlobalMessageEvent(msgText, msgSeverity)); + }; + } else { + return dispatch => { + dispatch(getClearGlobalMessageEvent()); + }; + } +} diff --git a/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js new file mode 100644 index 0000000..734696f --- /dev/null +++ b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js @@ -0,0 +1,53 @@ +/* + * ============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 globalAutoCompleteSearchBarActionTypes = keyMirror({ + SUGGESTION_FOUND: null, + SUGGESTION_CHANGED: null, + SUGGESTION_NOT_FOUND: null, + CLEAR_SUGGESTIONS_TEXT_FIELD: null, + CLEAR_SUGGESTIONS: null, + SUGGESTION_CLICKED: null, + NETWORK_ERROR: null, + SEARCH_WARNING_EVENT: null, + SEARCH_INVALID_TERMS: null +}); + +export const GLOBAL_SEARCH_URL = BASE_URL + '/search/querysearch/'; + +export const NO_MATCHES_FOUND = 'No Matches Found'; +export const ERROR_INVALID_SEARCH_TERMS = 'Invalid search terms'; +export const SEARCH_DEBOUNCE_TIME = 300; + +export const ICON_CLASS_SEARCH = 'fa fa-search fa-lg'; +export const ICON_CLASS_CLEAR = 'fa fa-times fa-lg'; +export const SEARCH_SELECTED_NODE_PATH = '/visualization/prepareVisualization'; + + + diff --git a/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarReducer.js b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarReducer.js new file mode 100644 index 0000000..1f52c08 --- /dev/null +++ b/src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarReducer.js @@ -0,0 +1,105 @@ +/* + * ============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 { + globalAutoCompleteSearchBarActionTypes, + NO_MATCHES_FOUND +} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js'; +import { + MESSAGE_LEVEL_WARNING, + MESSAGE_LEVEL_DANGER +} from 'utils/GlobalConstants.js'; + +export default (state = {}, action) => { + switch (action.type) { + case globalAutoCompleteSearchBarActionTypes.SUGGESTION_FOUND: + return { + ...state, + suggestions: action.data.suggestions, + cachedSuggestions: action.data.suggestions, + feedbackMsgText: action.data.errorMsg, + feedbackMsgSeverity: MESSAGE_LEVEL_DANGER + }; + case globalAutoCompleteSearchBarActionTypes.SUGGESTION_NOT_FOUND: + return { + ...state, + suggestions: [{ text: i18n(NO_MATCHES_FOUND)}], + cachedSuggestions: [{ + entityType: i18n(NO_MATCHES_FOUND) + }], + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + case globalAutoCompleteSearchBarActionTypes.CLEAR_SUGGESTIONS_TEXT_FIELD: + return { + ...state, + suggestions: [], + cachedSuggestions: [], + value: '', + feedbackMsgText: '', + feedbackMsgSeverity: '', + clearSearchText: false + }; + case globalAutoCompleteSearchBarActionTypes.CLEAR_SUGGESTIONS: + return { + ...state, + suggestions: [] + }; + case globalAutoCompleteSearchBarActionTypes.SUGGESTION_CHANGED: + return { + ...state, + value: action.data, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + case globalAutoCompleteSearchBarActionTypes.SUGGESTION_CLICKED: + return { + ...state, + selectedSuggestion: action.data.selectedSuggestion, + performPrepareVisualization: true, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + case globalAutoCompleteSearchBarActionTypes.NETWORK_ERROR: + return { + ...state, + suggestions: [], + cachedSuggestions: [], + feedbackMsgText: action.data.errorMsg, + feedbackMsgSeverity: MESSAGE_LEVEL_DANGER + }; + case globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT: + return { + ...state, + suggestions: [], + cachedSuggestions: [], + feedbackMsgText: action.data.errorMsg, + feedbackMsgSeverity: MESSAGE_LEVEL_WARNING + }; + } + return state; +}; diff --git a/src/app/inventory/Inventory.jsx b/src/app/inventory/Inventory.jsx new file mode 100644 index 0000000..de7120b --- /dev/null +++ b/src/app/inventory/Inventory.jsx @@ -0,0 +1,190 @@ +/* + * ============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 Grid from 'react-bootstrap/lib/Grid'; +import Row from 'react-bootstrap/lib/Row'; +import Col from 'react-bootstrap/lib/Col'; +import Clearfix from 'react-bootstrap/lib/Clearfix'; +import { + LineChart, Line, XAxis, YAxis, CartesianGrid, + Tooltip, ResponsiveContainer, Brush +} from 'recharts'; +import i18n from 'utils/i18n/i18n'; + +import TopographicMap from 'generic-components/map/TopographicMap.jsx'; +import { + onTopographicMapMounted, onCountByTypeLoad, onLoadTotalCountByDate +} from 'app/inventory/InventoryActions.js'; +import { + INVENTORY_TITLE, + TOTAL_ENTITY_COUNTS_BY_DATE_CHART, + COMPLEX_BY_LOCATION_TITLE, + ENTITIES_BY_TYPE_TITLE, + TOTAL_ENTITY_COUNT_TITLE +} from 'app/inventory/InventoryConstants.js'; +import InlineMessage from 'generic-components/InlineMessage/InlineMessage.jsx'; +import PaginatedTable from 'generic-components/paginatedTable/PaginatedTable.jsx'; +import { + dateFormatLocalTimeZoneMMDDYYYY, getTicks, getTicksData, sortDataByField +} from 'utils/DateTimeChartUtil.js'; +import TitledContainer from 'generic-components/titledContainer/TitledContainer.jsx'; +import {COLOR_BLUE} from 'utils/GlobalConstants.js'; + +const mapStateToProps = ({inventoryReducer}) => { + let { + mapPlotPoints = [], countByType = [], countByDate = [], + feedbackMsgText = '', feedbackMsgSeverity = '' + } = inventoryReducer; + + return { + mapPlotPoints, + countByType, + countByDate, + feedbackMsgText, + feedbackMsgSeverity + }; +}; + +const mapActionToProps = (dispatch) => { + return { + onMountQueryTopographicVisualization: (requestObject) => { + dispatch(onTopographicMapMounted(requestObject)); + }, onLoadCountByType: () => { + dispatch(onCountByTypeLoad()); + }, onLoadTotalCountByDate: () => { + dispatch(onLoadTotalCountByDate()); + } + }; +}; + +class Inventory extends Component { + + componentDidMount() { + let requestObject = { + entityType: 'complex' + }; + this.props.onMountQueryTopographicVisualization(requestObject); + this.props.onLoadCountByType(); + this.props.onLoadTotalCountByDate(); + } + + render() { + let { + mapPlotPoints, countByType, onLoadCountByType, countByDate, + feedbackMsgSeverity, feedbackMsgText + } = this.props; + + let tableDefinition = { + key: {name: 'Entity'}, + doc_count: {name: 'Count'} + }; + let paginationClasses = 'audit-pagination'; + let tableClasses = + 'inventory-table table table-striped table-bordered table-condensed'; + + const xAxisAttrName = 'date'; + const yAxisAttrName = 'count'; + const sortedData = sortDataByField(countByDate, xAxisAttrName); + const ticksArr = getTicks(sortedData, xAxisAttrName); + const completeData = getTicksData(sortedData, ticksArr, xAxisAttrName); + const completeSortedData = sortDataByField(completeData, xAxisAttrName); + + let totalEntities = 0; + let lastDate = ''; + if (sortedData.length > 0) { + lastDate = + dateFormatLocalTimeZoneMMDDYYYY(sortedData[sortedData.length - 1] + .date); + totalEntities = sortedData[sortedData.length - 1].count; + } + + return ( + <div> + <div className='secondary-header'> + <span className='secondary-title'>{i18n(INVENTORY_TITLE)}</span> + <InlineMessage level={feedbackMsgSeverity} + messageTxt={feedbackMsgText}/> + </div> + <Grid fluid={true}> + <Row> + <Col xs={3} sm={3} md={3}> + <TitledContainer title={TOTAL_ENTITY_COUNT_TITLE}> + <div className='total-entity-count'> + {totalEntities} + <span>{lastDate}</span> + </div> + </TitledContainer> + <TitledContainer title={ENTITIES_BY_TYPE_TITLE}> + <PaginatedTable + tableHeaders={tableDefinition} + displayHeader={false} + tableData={countByType} + activePage={1} + pageCount={1} + onPageIndexSelected={ () => onLoadCountByType()} + paginationClass={paginationClasses} + tableClass={tableClasses} + maxPaginationLinks={25}/> + </TitledContainer> + </Col> + <Clearfix visibleSmBlock/> + <Col xs={9} sm={9} md={9}> + <TitledContainer + title={i18n(TOTAL_ENTITY_COUNTS_BY_DATE_CHART.title)}> + <ResponsiveContainer width='100%' height={250}> + <LineChart data={completeSortedData} + margin={{ + top: 10, bottom: 10, left: 10, right: 70 + }}> + <XAxis dataKey={xAxisAttrName} ticks={ticksArr} + tickCount={ticksArr.length} + tickFormatter={dateFormatLocalTimeZoneMMDDYYYY}/> + <YAxis/> + <CartesianGrid strokeDasharray='3 3'/> + <Tooltip labelFormatter={dateFormatLocalTimeZoneMMDDYYYY}/> + <Brush dataKey={xAxisAttrName} + tickFormatter={dateFormatLocalTimeZoneMMDDYYYY} + height={20} stroke={COLOR_BLUE}/> + <Line + name={i18n(TOTAL_ENTITY_COUNTS_BY_DATE_CHART.yAxisLabel)} + type='monotone' dataKey={yAxisAttrName} + stroke={COLOR_BLUE} + connectNulls={true} activeDot={{r: 6}}/> + </LineChart> + </ResponsiveContainer> + </TitledContainer> + <TitledContainer title={i18n(COMPLEX_BY_LOCATION_TITLE)}> + <TopographicMap pointArray={mapPlotPoints}/> + </TitledContainer> + </Col> + </Row> + </Grid> + </div> + ); + } +} +export default connect(mapStateToProps, mapActionToProps)(Inventory); diff --git a/src/app/inventory/InventoryActions.js b/src/app/inventory/InventoryActions.js new file mode 100644 index 0000000..d3feab9 --- /dev/null +++ b/src/app/inventory/InventoryActions.js @@ -0,0 +1,170 @@ +/* + * ============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 { + GET, + POST_HEADER, + ERROR_RETRIEVING_DATA, + SAME_ORIGIN, + BACKEND_IP_ADDRESS +} from 'app/networking/NetworkConstants.js'; + +import { + INVENTORY_GEO_VISUALIZATION_SEARCH_URL, + GEO_VISUALIZATION_QUERY_STRING_PARAMETERS, + INVENTORY_COUNT_BY_TYPE_SEARCH_URL, + INVENTORY_COUNT_BY_DATE_SEARCH_URL, + InventoryActionTypes +} from 'app/inventory/InventoryConstants.js'; + +import {MESSAGE_LEVEL_DANGER} from 'utils/GlobalConstants.js'; + +function getSuccessfulTopographicVisualizationQueryEvent(responseJson) { + return { + type: InventoryActionTypes.TOPOGRAPHIC_QUERY_SUCCESS, + data: { + plotPoints: responseJson.plotPoints + } + }; +} + +function getFailedTopographicVisualizationQueryEvent() { + return { + type: InventoryActionTypes.TOPOGRAPHIC_QUERY_FAILED, + data: { + message: ERROR_RETRIEVING_DATA, + severity: MESSAGE_LEVEL_DANGER + } + }; +} + +function getSuccessfulCountByTypeQueryEvent(responseJson) { + return { + type: InventoryActionTypes.COUNT_BY_ENTITY_SUCCESS, + data: { + countByType: responseJson.result + } + }; +} + +function getFailedCountByTypeQueryEvent() { + return { + type: InventoryActionTypes.COUNT_BY_ENTITY_FAILED, + data: { + message: ERROR_RETRIEVING_DATA, + severity: MESSAGE_LEVEL_DANGER + } + }; +} + +function getSuccessfulCountsByDateQueryEvent(responseJson) { + return { + type: InventoryActionTypes.COUNT_BY_DATE_SUCCESS, + data: { + countByDate: responseJson.result + } + }; +} + +function getFailedCountByDateQueryEvent() { + return { + type: InventoryActionTypes.COUNT_BY_DATE_FAILED, + data: { + message: ERROR_RETRIEVING_DATA, + severity: MESSAGE_LEVEL_DANGER + } + }; +} + +function getDynamicTopographicQueryURL(entityType) { + return INVENTORY_GEO_VISUALIZATION_SEARCH_URL.replace(BACKEND_IP_ADDRESS, + BACKEND_IP_ADDRESS) + + GEO_VISUALIZATION_QUERY_STRING_PARAMETERS + + entityType; +} + +function getCountByTypeQueryURL() { + return INVENTORY_COUNT_BY_TYPE_SEARCH_URL.replace(BACKEND_IP_ADDRESS, + BACKEND_IP_ADDRESS); +} + +function getCountByDateQueryURL() { + return INVENTORY_COUNT_BY_DATE_SEARCH_URL.replace(BACKEND_IP_ADDRESS, + BACKEND_IP_ADDRESS); +} + +export function onLoadTotalCountByDate() { + return function (dispatch) { + fetch(getCountByDateQueryURL(), { + credentials: SAME_ORIGIN, + method: GET, + headers: POST_HEADER + }).then( + (response) => response.json() + ).then( + (responseJson) => dispatch( + getSuccessfulCountsByDateQueryEvent(responseJson)) + ).catch( + () => dispatch(getFailedCountByDateQueryEvent()) + ); + }; +} + +export function onCountByTypeLoad() { + return function (dispatch) { + fetch(getCountByTypeQueryURL(), { + credentials: SAME_ORIGIN, + method: GET, + headers: POST_HEADER + }).then( + (response) => response.json() + ).then( + (responseJson) => dispatch( + getSuccessfulCountByTypeQueryEvent(responseJson)) + ).catch( + () => dispatch(getFailedCountByTypeQueryEvent()) + ); + }; +} + +export function onTopographicMapMounted(requestObject) { + return function (dispatch) { + fetch(getDynamicTopographicQueryURL(requestObject.entityType), { + credentials: SAME_ORIGIN, + method: GET, + headers: POST_HEADER + }).then( + (response) => response.json() + ).then( + (responseJson) => dispatch( + getSuccessfulTopographicVisualizationQueryEvent(responseJson)) + ).catch( + () => { + dispatch(getFailedTopographicVisualizationQueryEvent()); + } + ); + }; +} + diff --git a/src/app/inventory/InventoryConstants.js b/src/app/inventory/InventoryConstants.js new file mode 100644 index 0000000..a7b3350 --- /dev/null +++ b/src/app/inventory/InventoryConstants.js @@ -0,0 +1,54 @@ +/* + * ============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 InventoryActionTypes = keyMirror({ + TOPOGRAPHIC_QUERY_SUCCESS: null, + TOPOGRAPHIC_QUERY_FAILED: null, + COUNT_BY_ENTITY_SUCCESS: null, + COUNT_BY_ENTITY_FAILED: null, + COUNT_BY_DATE_SUCCESS: null, + COUNT_BY_DATE_FAILED: null +}); + +export const INVENTORY_TITLE = 'Active Inventory'; +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 GEO_VISUALIZATION_QUERY_STRING_PARAMETERS = '/?entity='; + +export const TOTAL_ENTITY_COUNTS_BY_DATE_CHART = { + title: 'Total Entities By Date', + yAxisLabel: 'Entities', + emptyData: [{ + values: [] + }] +}; diff --git a/src/app/inventory/InventoryReducer.js b/src/app/inventory/InventoryReducer.js new file mode 100644 index 0000000..8e33885 --- /dev/null +++ b/src/app/inventory/InventoryReducer.js @@ -0,0 +1,67 @@ +/* + * ============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 {InventoryActionTypes} from './InventoryConstants.js'; + +export default(state = {}, action) => { + + switch (action.type) { + case InventoryActionTypes.TOPOGRAPHIC_QUERY_SUCCESS: + return { + ...state, + mapPlotPoints: action.data.plotPoints + }; + break; + + case InventoryActionTypes.COUNT_BY_ENTITY_SUCCESS: + return { + ...state, + countByType: action.data.countByType + }; + break; + + case InventoryActionTypes.COUNT_BY_DATE_SUCCESS: + return { + ...state, + countByDate: action.data.countByDate + }; + break; + + case InventoryActionTypes.TOPOGRAPHIC_QUERY_FAILED: + case InventoryActionTypes.COUNT_BY_ENTITY_FAILED: + case InventoryActionTypes.COUNT_BY_DATE_FAILED: + return { + ...state, + feedbackMsgSeverity: action.data.severity, + feedbackMsgText: action.data.message + }; + break; + + default: + break; + } + + return state; +}; diff --git a/src/app/main.app.jsx b/src/app/main.app.jsx new file mode 100644 index 0000000..e07ad52 --- /dev/null +++ b/src/app/main.app.jsx @@ -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. + */ + +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 React from 'react'; +import ReactDOM from 'react-dom'; + +import Application from './Application.jsx'; +import MainScreenWrapper from './MainScreenWrapper.jsx'; + +ReactDOM.render( + <Application><MainScreenWrapper /></Application>, + document.getElementById('main-app')); diff --git a/src/app/networking/NetworkCalls.js b/src/app/networking/NetworkCalls.js new file mode 100644 index 0000000..9128741 --- /dev/null +++ b/src/app/networking/NetworkCalls.js @@ -0,0 +1,70 @@ +/* + * ============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. + */ + + +function fetchRequest(URL, POST, POST_HEADER, BODY) { + return fetch(URL, { + credentials: 'same-origin', + method: POST, + headers: POST_HEADER, + body: BODY + }).then( + (response) => response.json() + ); +} + +function fetchRequestObj(URL, POST, POST_HEADER, BODY) { + return fetch(URL, { + credentials: 'same-origin', + method: POST, + headers: POST_HEADER, + body: BODY + }); +} + +module.exports = { + fetchRequest: fetchRequest, + fetchRequestObj: fetchRequestObj +}; + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/networking/NetworkConstants.js b/src/app/networking/NetworkConstants.js new file mode 100644 index 0000000..d39fe7b --- /dev/null +++ b/src/app/networking/NetworkConstants.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. + */ + +export const POST = 'POST'; +export const GET = 'GET'; +export const POST_HEADER = {'Accept': 'application/json'}; +export const SAME_ORIGIN = 'same-origin'; +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; +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/app/networking/NetworkUtil.js b/src/app/networking/NetworkUtil.js new file mode 100644 index 0000000..ded996b --- /dev/null +++ b/src/app/networking/NetworkUtil.js @@ -0,0 +1,151 @@ +/* + * ============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 { + 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 + let posFirstEqualSign = query.indexOf('='); + let newQuery = query.substring(posFirstEqualSign + 1); // remove the first + // 'attrName=' from + //'attrName=attrValue' + newQuery = newQuery.replace(/\,[^\=]+\=/gi, ' '); // remove all ', attrName=' + newQuery = newQuery.trim(); // remove whitespace at both ends, if any + + return { + 'maxResults': '10', + '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/tierSupport/TierSupport.jsx b/src/app/tierSupport/TierSupport.jsx new file mode 100644 index 0000000..d4b0f3b --- /dev/null +++ b/src/app/tierSupport/TierSupport.jsx @@ -0,0 +1,211 @@ +/* + * ============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 SplitPane from 'react-split-pane'; + +import ForceDirectedGraph from 'generic-components/graph/ForceDirectedGraph.jsx'; +import SelectedNodeDetails from 'app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx'; +import i18n from 'utils/i18n/i18n'; +import { + onNodeDetailsChange, + onNodeMenuChange, + splitPaneResize, + querySelectedNodeElement, + setNotificationText, + clearVIData +} from 'app/tierSupport/TierSupportActions.js'; +import { + TSUI_TITLE, + TSUI_NODE_DETAILS_INITIAL_WIDTH, + TSUI_NODE_DETAILS_MIN_WIDTH, + TSUI_GRAPH_MENU_NODE_DETAILS +} from './TierSupportConstants.js'; + +let mapStateToProps = ( + { + tierSupport: + { + tierSupportReducer, + globalAutoCompleteSearchBar + } + }) => { + + let { + forceDirectedGraphRawData = { + graphCounter: -1, + nodeDataArray: [], + linkDataArray: [], + graphMeta: {} + }, windowWidth = 500, + windowHeight = 500, + graphNodeSelectedMenu = TSUI_GRAPH_MENU_NODE_DETAILS, + feedbackMsgText = '', + feedbackMsgSeverity = '' + } = tierSupportReducer; + + let { + performPrepareVisualization = false, + selectedSuggestion = {} + } = globalAutoCompleteSearchBar; + return { + forceDirectedGraphRawData, + windowWidth, + windowHeight, + graphNodeSelectedMenu, + performPrepareVisualization, + selectedSuggestion, + feedbackMsgText, + feedbackMsgSeverity + }; +}; + +let mapActionToProps = (dispatch) => { + return { + onNodeSelected: (requestObject) => { + dispatch(onNodeDetailsChange(requestObject)); + }, + onNodeMenuSelect: (selectedMenu) => { + dispatch(onNodeMenuChange(selectedMenu.buttonId)); + }, + onSplitPaneResize: (initialLoad) => { + dispatch(splitPaneResize(initialLoad)); + }, + onNewVIParam: (param) => { + dispatch(querySelectedNodeElement(param)); + }, + onMessageStateChange: (msgText, msgSeverity) => { + dispatch(setNotificationText(msgText, msgSeverity)); + }, + onRequestClearData: () => { + dispatch(clearVIData()); + } + }; +}; + +class TierSupport extends Component { + static propTypes = { + forceDirectedGraphRawData: React.PropTypes.object, + windowWidth: React.PropTypes.number, + windowHeight: React.PropTypes.number, + graphNodeSelectedMenu: React.PropTypes.string, + feedbackMsgText: React.PropTypes.string, + feedbackMsgSeverity: React.PropTypes.string + }; + + componentWillReceiveProps(nextProps) { + if (nextProps.match.params.viParam && + nextProps.match.params.viParam !== + this.props.match.params.viParam) { + this.props.onNewVIParam(nextProps.match.params.viParam); + } + + if (nextProps.feedbackMsgText !== this.props.feedbackMsgText) { + this.props.onMessageStateChange(nextProps.feedbackMsgText, + nextProps.feedbackMsgSeverity); + } + } + + componentWillMount() { + if (this.props.match.params.viParam) { + this.props.onNewVIParam(this.props.match.params.viParam); + } else { + this.props.onRequestClearData(); + } + } + + componentDidMount() { + this.props.onSplitPaneResize(true); + } + + componentWillUnmount() { + // resetting to default (empty screen) + this.props.onRequestClearData(); + } + + render() { + const { + forceDirectedGraphRawData, + onNodeSelected, + windowWidth, + windowHeight, + onSplitPaneResize, + onNodeMenuSelect + } = this.props; + let currentSelectedMenu = this.getCurrentSelectedMenu(); + + //Temp code for a demo, will be removed as Vis library is updated + let currentNodeButton = 'NODE_DETAILS'; + // End temp code + + return ( + <div className='tier-support-ui'> + <div className='secondary-header'> + <span className='secondary-title'>{i18n(TSUI_TITLE)}</span> + </div> + <SplitPane + split='vertical' + enableResizing='true' + onDragFinished={ () => { + onSplitPaneResize(false); + } } + defaultSize={TSUI_NODE_DETAILS_INITIAL_WIDTH} + minSize={TSUI_NODE_DETAILS_MIN_WIDTH} + maxSize={-200} + primary='second'> + <div> + <ForceDirectedGraph + viewWidth={windowWidth} + viewHeight={windowHeight} + graphData={forceDirectedGraphRawData} + nodeSelectedCallback={(nodeData) => { + onNodeSelected(nodeData); + }} + nodeButtonSelectedCallback={(selectedMenuId) => { + onNodeMenuSelect(selectedMenuId); + }} + currentlySelectedNodeView={currentNodeButton}/> + </div> + <div> + {currentSelectedMenu} + </div> + </SplitPane> + </div> + ); + } + + getCurrentSelectedMenu() { + switch (this.props.graphNodeSelectedMenu) { + case TSUI_GRAPH_MENU_NODE_DETAILS: + if (!this.nodeDetails) { + this.nodeDetails = <SelectedNodeDetails/>; + } + return this.nodeDetails; + } + } +} + +export default connect(mapStateToProps, mapActionToProps)(TierSupport); diff --git a/src/app/tierSupport/TierSupportActions.js b/src/app/tierSupport/TierSupportActions.js new file mode 100644 index 0000000..d6f5e5a --- /dev/null +++ b/src/app/tierSupport/TierSupportActions.js @@ -0,0 +1,175 @@ +/* + * ============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 {tierSupportActionTypes, + TS_BACKEND_SEARCH_SELECTED_NODE_URL} from 'app/tierSupport/TierSupportConstants.js'; +import { + POST, + POST_HEADER, + ERROR_RETRIEVING_DATA, + NO_RESULTS_FOUND +} from 'app/networking/NetworkConstants.js'; +import networkCall from 'app/networking/NetworkCalls.js'; +import { + getSetGlobalMessageEvent, + getClearGlobalMessageEvent +} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js'; +import { + STATUS_CODE_204_NO_CONTENT, + STATUS_CODE_3XX_REDIRECTION, + STATUS_CODE_5XX_SERVER_ERROR +} from 'utils/GlobalConstants.js'; + +function createOnNodeDetailsChangeEvent(newDetails) { + return { + type: tierSupportActionTypes.TS_GRAPH_NODE_SELECTED, + data: newDetails + }; +} + +function createSplitPaneResizeEvent(initialLoad) { + return { + type: tierSupportActionTypes.SPLIT_PANE_RESIZE, + data: initialLoad + }; +} + +function createOnNodeMenuSelectEvent(selectedMenu) { + return { + type: tierSupportActionTypes.TS_GRAPH_NODE_MENU_SELECTED, + data: selectedMenu + }; +} + +export function onNodeDetailsChange(newDetails) { + return dispatch => { + dispatch(createOnNodeDetailsChangeEvent(newDetails)); + }; +} + +export function splitPaneResize(initialLoad) { + return dispatch => { + dispatch(createSplitPaneResizeEvent(initialLoad)); + }; +} + +export function onNodeMenuChange(selectedMenu) { + return dispatch => { + dispatch(createOnNodeMenuSelectEvent(selectedMenu)); + }; +} + +function createNodeDetailsFoundEvent(nodeDetails) { + return { + type: tierSupportActionTypes.TS_NODE_SEARCH_RESULTS, + data: nodeDetails + }; +} + +function noNodeDetailsFoundEvent(errorText) { + return { + type: tierSupportActionTypes.TS_NODE_SEARCH_NO_RESULTS, + data: {errorMsg: errorText} + }; +} + +function getInvalidSelectedNodeSearchEvent(errorText) { + return { + type: tierSupportActionTypes.TIER_SUPPORT_NETWORK_ERROR, + data: {value: errorText, errorMsg: ERROR_RETRIEVING_DATA} + }; +} + +export function clearVIData() { + return { + type: tierSupportActionTypes.TIER_SUPPORT_CLEAR_DATA + }; +} + +export function fetchSelectedNodeElement(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( + (responseJson) => { + if (responseJson.nodes.length > 0) { + dispatch(createNodeDetailsFoundEvent(responseJson)); + } else { + dispatch(noNodeDetailsFoundEvent(NO_RESULTS_FOUND)); + } + } + ).catch( + (errorCode) => { + if (errorCode.message >= STATUS_CODE_5XX_SERVER_ERROR) { + dispatch(getInvalidSelectedNodeSearchEvent(ERROR_RETRIEVING_DATA)); + } else { + // TODO - assuming 204 status, but should include additional + // statuses in the future with proper messaging in order to return + // better messaging + dispatch(noNodeDetailsFoundEvent(NO_RESULTS_FOUND)); + } + } + ); + }; +} + +export function querySelectedNodeElement( + searchHashId, selectedNodeFetchRequest) { + let payload = { + hashId: searchHashId + }; + + if (selectedNodeFetchRequest === undefined) { + let postBody = JSON.stringify(payload); + selectedNodeFetchRequest = + () => networkCall.fetchRequestObj(TS_BACKEND_SEARCH_SELECTED_NODE_URL, POST, + POST_HEADER, postBody); + } + + return dispatch => { + dispatch(fetchSelectedNodeElement(selectedNodeFetchRequest)); + }; +} + +export function setNotificationText(msgText, msgSeverity) { + if (msgText.length > 0) { + return dispatch => { + dispatch( + getSetGlobalMessageEvent(msgText, msgSeverity)); + }; + } else { + return dispatch => { + dispatch(getClearGlobalMessageEvent()); + }; + } +} diff --git a/src/app/tierSupport/TierSupportConstants.js b/src/app/tierSupport/TierSupportConstants.js new file mode 100644 index 0000000..ca7b512 --- /dev/null +++ b/src/app/tierSupport/TierSupportConstants.js @@ -0,0 +1,49 @@ +/* + * ============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 tierSupportActionTypes = keyMirror({ + TIER_SUPPORT_NETWORK_ERROR: null, + TS_NODE_SEARCH: null, + TS_NODE_SEARCH_RESULTS: null, + TS_NODE_SEARCH_NO_RESULTS: null, + TS_GRAPH_DATA_RESULTS: null, + TS_GRAPH_NODE_SELECTED: null, + TS_GRAPH_NODE_MENU_SELECTED: null, + SPLIT_PANE_RESIZE: null, + TIER_SUPPORT_CLEAR_DATA: null +}); + +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_TITLE = 'View & Inspect'; +export const TSUI_GRAPH_MENU_NODE_DETAILS = 'NODE_DETAILS'; +export const SEARCH_SELECTED_NODE_PATH = '/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 new file mode 100644 index 0000000..6e5e022 --- /dev/null +++ b/src/app/tierSupport/TierSupportReducer.js @@ -0,0 +1,110 @@ +/* + * ============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 ForceDirectedGraph from 'generic-components/graph/ForceDirectedGraph.jsx'; +import {aaiActionTypes} from 'app/MainScreenWrapperConstants.js'; +import { + tierSupportActionTypes, TSUI_GRAPH_MENU_NODE_DETAILS +} from 'app/tierSupport/TierSupportConstants.js'; +import SelectedNodeDetailsReducer from 'app/tierSupport/selectedNodeDetails/SelectedNodeDetailsReducer.js'; +import GlobalAutoCompleteSearchBarReducer from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarReducer.js'; +import { + MESSAGE_LEVEL_DANGER, MESSAGE_LEVEL_WARNING +} from 'utils/GlobalConstants.js'; +import { + globalAutoCompleteSearchBarActionTypes +} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js'; + +export default combineReducers({ + selectedNodeDetails: SelectedNodeDetailsReducer, + globalAutoCompleteSearchBar: GlobalAutoCompleteSearchBarReducer, + tierSupportReducer: (state = {}, action) => { + switch (action.type) { + case tierSupportActionTypes.TS_NODE_SEARCH_RESULTS: + let graphData = ForceDirectedGraph.generateNewProps(action.data.nodes, action.data.links, + action.data.graphMeta); + + return { + ...state, + forceDirectedGraphRawData: graphData, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + case tierSupportActionTypes.TS_GRAPH_NODE_MENU_SELECTED: + return { + ...state, graphNodeSelectedMenu: action.data + }; + case tierSupportActionTypes.TS_NODE_SEARCH_NO_RESULTS: + let emptyNodesAndLinksNoResults = ForceDirectedGraph.generateNewProps([], [], {}); + return { + ...state, + forceDirectedGraphRawData: emptyNodesAndLinksNoResults, + graphNodeSelectedMenu: TSUI_GRAPH_MENU_NODE_DETAILS, + feedbackMsgText: action.data.errorMsg, + feedbackMsgSeverity: MESSAGE_LEVEL_WARNING + }; + case tierSupportActionTypes.TIER_SUPPORT_NETWORK_ERROR: + let emptyNodesAndLinksNetworkError = ForceDirectedGraph.generateNewProps([], [], {}); + return { + ...state, + forceDirectedGraphRawData: emptyNodesAndLinksNetworkError, + graphNodeSelectedMenu: TSUI_GRAPH_MENU_NODE_DETAILS, + feedbackMsgText: action.data.errorMsg, + feedbackMsgSeverity: MESSAGE_LEVEL_DANGER + }; + case tierSupportActionTypes.TIER_SUPPORT_CLEAR_DATA: + let emptyNodesAndLinksClearData = ForceDirectedGraph.generateNewProps([], [], {}); + return { + ...state, + forceDirectedGraphRawData: emptyNodesAndLinksClearData, + graphNodeSelectedMenu: TSUI_GRAPH_MENU_NODE_DETAILS, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + case globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT: + let emptyNodesAndLinksWarningEvent = ForceDirectedGraph.generateNewProps([], [], {}); + return { + ...state, + forceDirectedGraphRawData: emptyNodesAndLinksWarningEvent, + graphNodeSelectedMenu: TSUI_GRAPH_MENU_NODE_DETAILS + }; + case aaiActionTypes.AAI_WINDOW_RESIZE: + case tierSupportActionTypes.SPLIT_PANE_RESIZE: + let splitPaneLeftSideElement = document.getElementsByClassName('Pane1'); + if (splitPaneLeftSideElement.length > 0) { + let width = splitPaneLeftSideElement[0].offsetWidth; + + return { + ...state, windowWidth: width, windowHeight: splitPaneLeftSideElement[0].offsetHeight + }; + } else { + return state; + } + } + + return state; + } +}); diff --git a/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx new file mode 100644 index 0000000..e04aca2 --- /dev/null +++ b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx @@ -0,0 +1,104 @@ +/* + * ============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 {connect} from 'react-redux'; +import React, {Component} from 'react'; +import Table from 'react-bootstrap/lib/Table'; +import i18n from 'utils/i18n/i18n'; +import { + SELECTED_NODE_TITLE, + NO_SELECTION, + SELECTED_NODE_TABLE_COLUMN_NAMES +} from 'app/tierSupport/selectedNodeDetails/SelectedNodeDetailsConstants.js'; + +let mapStateToProps = ({tierSupport: {selectedNodeDetails}}) => { + let {nodeData = [], nodeType = '', uid = ''} = selectedNodeDetails; + + return { + nodeData, + nodeType, + uid + }; +}; + +class SelectedNodeDetails extends Component { + static propTypes = { + nodeData: React.PropTypes.array, + nodeType: React.PropTypes.string, + uid: React.PropTypes.string + }; + + render() { + const {nodeData, nodeType, uid} = this.props; + + let tableClass = 'ts-selected-node-table'; + let noSelectionMessageClass = 'hidden'; + let tableColumns = []; + let tableRows = []; + + if (Object.keys(nodeData).length > 0) { + let cellClassName = ''; + for (let i = 1; i <= SELECTED_NODE_TABLE_COLUMN_NAMES.length; i++) { + cellClassName = (i % 2 ? 'left-column-cell' : 'right-column-cell'); + tableColumns.push(<th className={cellClassName} key={i}> + {i18n(SELECTED_NODE_TABLE_COLUMN_NAMES[i - 1])} + </th>); + } + + for (var key in nodeData) { + let value = nodeData[key]; + tableRows.push( + <tr key={key}> + <td className='left-column-cell'>{key}</td> + <td className='right-column-cell'>{value}</td> + </tr> + ); + } + } else { + tableClass = 'hidden'; + noSelectionMessageClass = ''; + } + + return ( + <div className='ts-selected-node-details'> + <h1>{i18n(SELECTED_NODE_TITLE)}</h1> + <h2>{nodeType}</h2> + <span>{uid}</span> + <Table bsClass={tableClass}> + <thead> + <tr> + {tableColumns} + </tr> + </thead> + <tbody> + {tableRows} + </tbody> + </Table> + <p className={noSelectionMessageClass}>{i18n(NO_SELECTION)}</p> + </div> + ); + } +} +export default connect(mapStateToProps)(SelectedNodeDetails); diff --git a/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetailsConstants.js b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetailsConstants.js new file mode 100644 index 0000000..e12cbed --- /dev/null +++ b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetailsConstants.js @@ -0,0 +1,48 @@ +/* + * ============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 SELECTED_NODE_TITLE = 'Node Details'; +export const NO_SELECTION = 'Search for a service to view its details'; +export const SELECTED_NODE_TABLE_COLUMN_NAMES = ['Attribute', 'Value']; +export const TABLE_DATA = [ + ['equipment-role', 'UCPE'], + ['in-maint', 'false'], + ['ipv4-oam-addres', '1.22.1.5'], + ['is-closed-loop-disabled', 'false'], + ['management-option', 'ATT'], + ['nm-lan-v6-address', 'FE80:0000:0AB0:0000:0207:B3FF:FE1E:1202'], + ['operational-state', 'PROV'], + ['orchestration-status', 'created'], + ['resource-version', '146650180'], + ['service-id', 'Ud7bb0a21-66f2-4e6d-87d9-9ef3ced63ae4CPE'], + ['vcpu', '1'], + ['vdisk', '20'], + ['vdisk-units', 'GB'], + ['vmemory', '12'], + ['vmemory-units', 'GB'], + ['vnf-id', 'b574e9e3-0a3d-4304-9c5-dd-su-gc21512'], + ['vnf-name', 'USETESORLFL0109UJSW01'], + ['vnf-type', 'SW'], +]; diff --git a/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetailsReducer.js b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetailsReducer.js new file mode 100644 index 0000000..e743a70 --- /dev/null +++ b/src/app/tierSupport/selectedNodeDetails/SelectedNodeDetailsReducer.js @@ -0,0 +1,72 @@ +/* + * ============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 {tierSupportActionTypes} from 'app/tierSupport/TierSupportConstants.js'; +import { + globalAutoCompleteSearchBarActionTypes +} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js'; + +export default (state = {}, action) => { + switch (action.type) { + case tierSupportActionTypes.TS_NODE_SEARCH_RESULTS: + for (const node of action.data.nodes) { + if (node.nodeMeta.searchTarget === true) { + return { + ...state, + nodeData: node.itemProperties, + nodeType: node.itemType, + uid: node.itemNameValue + }; + } + } + return { + ...state, + nodeData: [], + nodeType: '', + uid: '' + }; + + case tierSupportActionTypes.TS_GRAPH_NODE_SELECTED: + return { + ...state, + nodeData: action.data.itemProperties, + nodeType: action.data.itemType, + uid: action.data.itemNameValue + }; + + // else fall through to the TIER_SUPPORT_CLEAR_DATA case + case globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT: + case tierSupportActionTypes.TIER_SUPPORT_NETWORK_ERROR: + case tierSupportActionTypes.TIER_SUPPORT_CLEAR_DATA: + case tierSupportActionTypes.TS_NODE_SEARCH_NO_RESULTS: + return { + ...state, + nodeData: [], + nodeType: '', + uid: '' + }; + } + return state; +}; diff --git a/src/app/vnfSearch/VnfSearch.jsx b/src/app/vnfSearch/VnfSearch.jsx new file mode 100644 index 0000000..f1f69f5 --- /dev/null +++ b/src/app/vnfSearch/VnfSearch.jsx @@ -0,0 +1,129 @@ +/* + * ============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 { + VNF_TITLE, + VNFS_ROUTE, + DEFAULT_VNFS_SEARCH_HASH +} from 'app/vnfSearch/VnfSearchConstants.js'; +import { + processTotalVnfVisualizationOnSearchChange, + processOrchStatusVisualizationOnSearchChange, + processProvStatusVisualizationOnSearchChange, + setNotificationText +} from 'app/vnfSearch/VnfSearchActions.js'; +import VnfSearchOrchStatusVisualizations from 'app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx'; +import VnfSearchProvStatusVisualizations from 'app/vnfSearch/VnfSearchProvStatusVisualization.jsx'; +import VnfSearchTotalCountVisualization from 'app/vnfSearch/VnfSearchTotalCountVisualization.jsx'; +import i18n from 'utils/i18n/i18n'; +import {changeUrlAddress, buildRouteObj} from 'utils/Routes.js'; + +const mapStateToProps = ({vnfSearch}) => { + let { + feedbackMsgText = '', + feedbackMsgSeverity = '' + } = vnfSearch; + + return { + feedbackMsgText, + feedbackMsgSeverity + }; +}; + +let mapActionToProps = (dispatch) => { + return { + onReceiveNewParams: (vnfParam) => { + dispatch(processTotalVnfVisualizationOnSearchChange(vnfParam)); + dispatch(processOrchStatusVisualizationOnSearchChange(vnfParam)); + dispatch(processProvStatusVisualizationOnSearchChange(vnfParam)); + }, + onMessageStateChange: (msgText, msgSeverity) => { + dispatch(setNotificationText(msgText, msgSeverity)); + } + }; +}; + +class vnfSearch extends Component { + componentWillMount() { + 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); + } + + if (this.props.feedbackMsgText) { + this.props.onMessageStateChange(this.props.feedbackMsgText, + this.props.feedbackMsgSeverity); + } + } + + 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); + } + } + + componentWillUnmount() { + // resetting to default params so on relaunch there will be no + // visibility of old searches + this.props.onReceiveNewParams(DEFAULT_VNFS_SEARCH_HASH); + } + + render() { + return ( + <div> + <div className='secondary-header'> + <span className='secondary-title'>{i18n(VNF_TITLE)}</span> + </div> + <VnfSearchTotalCountVisualization /> + <VnfSearchProvStatusVisualizations /> + <VnfSearchOrchStatusVisualizations /> + </div> + ); + } +} +export default connect(mapStateToProps, mapActionToProps)(vnfSearch); diff --git a/src/app/vnfSearch/VnfSearchActions.js b/src/app/vnfSearch/VnfSearchActions.js new file mode 100644 index 0000000..0f31e09 --- /dev/null +++ b/src/app/vnfSearch/VnfSearchActions.js @@ -0,0 +1,215 @@ +/* + * ============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 { + vnfActionTypes, + VNF_RESULT_URL +} from 'app/vnfSearch/VnfSearchConstants.js'; + +import { + getVnfProvStatusQueryString, + getVnfOrchStatusQueryString, + getVnfCountQueryString +} from 'app/networking/NetworkUtil.js'; +import { + POST, + POST_HEADER, + ERROR_RETRIEVING_DATA +} from 'app/networking/NetworkConstants.js'; +import { + getSetGlobalMessageEvent, + getClearGlobalMessageEvent +} from 'app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js'; + +let fetch = require('node-fetch'); +fetch.Promise = require('es6-promise').Promise; + +const itemKeyWord = 'key'; +const countKeyWord = 'doc_count'; + +function getInvalidQueryEvent() { + return { + type: vnfActionTypes.VNF_NETWORK_ERROR, + 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 = [ + { + 'values': dataPoints + } + ]; + + 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 + }; + } +} + +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] + }); + } + + let newOrchStatusChartData = [ + { + 'values': dataPoints + } + ]; + + 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 + }; + } +} + +function getTotalVnfEvent(responseJson) { + if (responseJson && responseJson.count && responseJson.count > 0) { + return { + type: vnfActionTypes.TOTAL_VNF_COUNT_RECEIVED, + data: {count: responseJson.count} + }; + } + else { + return { + type: vnfActionTypes.ERROR_NO_COUNT_RECEIVED + }; + } +} + +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()); + } + ); + }; +} + +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()); + } + ); + }; +} + +export function processTotalVnfVisualizationOnSearchChange(requestObject) { + return dispatch => { + return fetch(VNF_RESULT_URL + '/count', { + method: POST, + headers: POST_HEADER, + body: JSON.stringify( + getVnfCountQueryString(requestObject)) + }).then( + (response) => response.json() + ).then( + (responseJson) => { + dispatch(getTotalVnfEvent(responseJson)); + } + ).catch( + () => { + dispatch(getInvalidQueryEvent()); + } + ); + }; +} + +export function setNotificationText(msgText, msgSeverity) { + if (msgText.length > 0) { + return dispatch => { + dispatch( + getSetGlobalMessageEvent(msgText, msgSeverity)); + }; + } else { + return dispatch => { + dispatch(getClearGlobalMessageEvent()); + }; + } +} diff --git a/src/app/vnfSearch/VnfSearchConstants.js b/src/app/vnfSearch/VnfSearchConstants.js new file mode 100644 index 0000000..d54cd88 --- /dev/null +++ b/src/app/vnfSearch/VnfSearchConstants.js @@ -0,0 +1,71 @@ +/* + * ============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 VNF_TITLE = 'VNFs'; + +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 +}); + +export const CHART_PROV_STATUS = { + title: 'VNFs By Provisioning Status', + yAxisLabel: 'VNFs', + xAxisLabel: 'VNFs', + 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': [ + { + 'x': 'No data discovered for Orchestration Status', + 'y': 0 + } + ]}] +}; + +export const TOTAL_VNF_COUNT = { + title: 'Total VNFs', + emptyValue: 0 +}; + +export const VNF_RESULT_URL = BASE_URL + '/search/summarybyentitytype'; + +export const DEFAULT_VNFS_SEARCH_HASH = '2172a3c25ae56e4995038ffbc1f055692bfc76c0b8ceda1205bc745a9f7a805d'; +export const VNFS_ROUTE = 'vnfSearch'; diff --git a/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx b/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx new file mode 100644 index 0000000..e72f3f6 --- /dev/null +++ b/src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx @@ -0,0 +1,95 @@ +/* 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_ORCH_STATUS} from 'app/vnfSearch/VnfSearchConstants.js'; +import {COLOR_BLUE} from 'utils/GlobalConstants.js'; + + +let mapStateToProps = ({vnfSearch}) => { + let { + processedOrchStatusCountChartData = CHART_ORCH_STATUS.emptyData + } = vnfSearch; + + return { + processedOrchStatusCountChartData + }; +}; + +class VnfSearchOrchStatusVisualizations extends Component { + + render() { + let { + processedOrchStatusCountChartData + } = this.props; + + let visualizationClass = 'visualizations'; + if (processedOrchStatusCountChartData[0].values === + null || + processedOrchStatusCountChartData[0].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_ORCH_STATUS.title)}</h3> + <ResponsiveContainer width='100%' height={300}> + <BarChart data={processedOrchStatusCountChartData[0].values}> + <XAxis dataKey={xAxisAttrName}/> + <YAxis /> + <CartesianGrid strokeDasharray='3 3'/> + <Tooltip/> + <Bar name={i18n(CHART_ORCH_STATUS.yAxisLabel)} + dataKey={yAxisAttrName} fill={COLOR_BLUE}/> + </BarChart> + </ResponsiveContainer> + </div> + </div> + </div> + ); + } + +} +export default connect(mapStateToProps)( + VnfSearchOrchStatusVisualizations); diff --git a/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx b/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx new file mode 100644 index 0000000..3d9d524 --- /dev/null +++ b/src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx @@ -0,0 +1,97 @@ +/* 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_PROV_STATUS} from 'app/vnfSearch/VnfSearchConstants.js'; +import {COLOR_BLUE} from 'utils/GlobalConstants.js'; + +let mapStateToProps = ({vnfSearch}) => { + let { + processedProvStatusCountChartData = CHART_PROV_STATUS.emptyData + } = vnfSearch; + + return { + processedProvStatusCountChartData + }; +}; + +class VnfSearchProvStatusVisualization extends Component { + static propTypes = { + processedProvStatusCountChartData: React.PropTypes.array + }; + + render() { + let { + processedProvStatusCountChartData + } = this.props; + + let visualizationClass = 'visualizations'; + if (processedProvStatusCountChartData[0].values === + null || + processedProvStatusCountChartData[0].values.size <= + 0) { + visualizationClass = 'visualizations hidden'; + } + const xAxisAttrName = 'x'; + const yAxisAttrName = 'y'; + + return ( + <div id='audit-visualizations' className={visualizationClass}> + <div className='visualization-charts'> + <div className='visualization-side-by-side-70'> + <h3>{i18n(CHART_PROV_STATUS.title)}</h3> + <ResponsiveContainer width='100%' height={300}> + <BarChart + data={processedProvStatusCountChartData[0].values}> + <XAxis dataKey={xAxisAttrName}/> + <YAxis /> + <CartesianGrid strokeDasharray='3 3'/> + <Tooltip/> + <Bar name={i18n(CHART_PROV_STATUS.xAxisLabel)} + dataKey={yAxisAttrName} fill={COLOR_BLUE}/> + </BarChart> + </ResponsiveContainer> + </div> + </div> + </div> + ); + } + +} +export default connect(mapStateToProps)(VnfSearchProvStatusVisualization); diff --git a/src/app/vnfSearch/VnfSearchReducer.js b/src/app/vnfSearch/VnfSearchReducer.js new file mode 100644 index 0000000..0a6803a --- /dev/null +++ b/src/app/vnfSearch/VnfSearchReducer.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 {vnfActionTypes} from 'app/vnfSearch/VnfSearchConstants.js'; +import { + CHART_ORCH_STATUS, + CHART_PROV_STATUS, + TOTAL_VNF_COUNT +} from 'app/vnfSearch/VnfSearchConstants.js'; +import {ERROR_RETRIEVING_DATA} from 'app/networking/NetworkConstants.js'; +import {MESSAGE_LEVEL_DANGER} from 'utils/GlobalConstants.js'; +import { + globalAutoCompleteSearchBarActionTypes +} from 'app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js'; + +export default (state = {}, action) => { + let data = action.data; + switch (action.type) { + + case vnfActionTypes.COUNT_BY_PROV_STATUS_RECEIVED: + return { + ...state, + processedProvStatusCountChartData: data.provStatusCountChartData.chartData, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + + case vnfActionTypes.COUNT_BY_ORCH_STATUS_RECEIVED: + return { + ...state, + processedOrchStatusCountChartData: data.orchStatusCountChartData.chartData, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + case vnfActionTypes.TOTAL_VNF_COUNT_RECEIVED: + return { + ...state, + count: data.count, + feedbackMsgText: '', + feedbackMsgSeverity: '' + }; + case vnfActionTypes.ERROR_NO_DATA_FOR_PROV_STATUS_IN_SEARCH_RANGE_RECEIVED: + return { + ...state, + processedProvStatusCountChartData: CHART_PROV_STATUS.emptyData, + }; + case vnfActionTypes.ERROR_NO_DATA_FOR_ORCH_STATUS_IN_SEARCH_RANGE_RECEIVED: + return { + ...state, + processedOrchStatusCountChartData: CHART_ORCH_STATUS.emptyData, + }; + case vnfActionTypes.ERROR_NO_COUNT_RECEIVED: + return { + ...state, + count: TOTAL_VNF_COUNT.emptyValue, + }; + case vnfActionTypes.VNF_NETWORK_ERROR: + 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 + }; + case globalAutoCompleteSearchBarActionTypes.SEARCH_WARNING_EVENT: + return { + ...state, + processedProvStatusCountChartData: CHART_PROV_STATUS.emptyData, + processedOrchStatusCountChartData: CHART_ORCH_STATUS.emptyData, + count: TOTAL_VNF_COUNT.emptyValue + }; + } + + return state; +}; diff --git a/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx b/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx new file mode 100644 index 0000000..326dae9 --- /dev/null +++ b/src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx @@ -0,0 +1,75 @@ +/* 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 i18n from 'utils/i18n/i18n'; + +import {TOTAL_VNF_COUNT} from 'app/vnfSearch/VnfSearchConstants.js'; + +let mapStateToProps = ({vnfSearch}) => { + let { + count = TOTAL_VNF_COUNT.emptyValue + } = vnfSearch; + + return { + count + }; +}; + +class VnfSearchTotalCountVisualization extends Component { + static propTypes = { + count: React.PropTypes.number + }; + + render() { + let { + count + } = this.props; + + let visualizationClass = 'visualizations'; + if (count === null) { + visualizationClass = 'visualizations hidden'; + } + + return ( + <div id='audit-visualizations' className={visualizationClass}> + <div className='visualization-charts'> + <div className='visualization-side-by-side-30'> + <span> </span> + <h3>{i18n(TOTAL_VNF_COUNT.title)}</h3> + <div className='total-box-entity-count'> + <span>{count}</span> + </div> + </div> + </div> + </div> + ); + } + +} +export default connect(mapStateToProps)(VnfSearchTotalCountVisualization); |