Adding filter bar 11/25811/1
authorShawn Severin <shawn.severin@amdocs.com>
Thu, 7 Dec 2017 20:19:25 +0000 (15:19 -0500)
committerShawn Severin <shawn.severin@amdocs.com>
Thu, 7 Dec 2017 20:19:46 +0000 (15:19 -0500)
Issue-ID: AAI-543
Change-Id: I18ec69f4585a9f01feafd009fcd30493a039b064
Signed-off-by: Shawn Severin <shawn.severin@amdocs.com>
63 files changed:
src/app/AppStore.js
src/app/GlobalInlineMessageBar/GlobalInlineMessageBarActions.js
src/app/GlobalInlineMessageBar/GlobalInlineMessageBarReducer.js
src/app/MainScreenHeader.jsx
src/app/MainScreenWrapper.jsx
src/app/MainScreenWrapperActionHelper.js
src/app/MainScreenWrapperConstants.js
src/app/MainScreenWrapperReducer.js
src/app/contextHandler/ContextHandlerActions.js [new file with mode: 0644]
src/app/contextHandler/ContextHandlerConstants.js [new file with mode: 0644]
src/app/extensibility/ExtensibilityReducer.js [new file with mode: 0644]
src/app/extensibility/index.js [new file with mode: 0644]
src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBar.jsx
src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarActions.js
src/app/globalAutoCompleteSearchBar/GlobalAutoCompleteSearchBarConstants.js
src/app/inventory/Inventory.jsx
src/app/inventory/InventoryConstants.js
src/app/main.app.jsx
src/app/networking/NetworkConstants.js
src/app/networking/NetworkUtil.js
src/app/overlays/OverlayImports.js [new file with mode: 0644]
src/app/tierSupport/TierSupport.jsx
src/app/tierSupport/TierSupportActions.js
src/app/tierSupport/TierSupportConstants.js
src/app/tierSupport/TierSupportReducer.js
src/app/tierSupport/selectedNodeDetails/SelectedNodeDetails.jsx
src/app/vnfSearch/VnfSearch.jsx
src/app/vnfSearch/VnfSearchActions.js
src/app/vnfSearch/VnfSearchConstants.js
src/app/vnfSearch/VnfSearchNfRoleVisualization.jsx [new file with mode: 0644]
src/app/vnfSearch/VnfSearchNfTypeVisualization.jsx [new file with mode: 0644]
src/app/vnfSearch/VnfSearchOrchestratedStatusVisualization.jsx
src/app/vnfSearch/VnfSearchProvStatusVisualization.jsx
src/app/vnfSearch/VnfSearchReducer.js
src/app/vnfSearch/VnfSearchTotalCountVisualization.jsx
src/editAttributes/AppStore.js [new file with mode: 0644]
src/editAttributes/Application.jsx [new file with mode: 0644]
src/editAttributes/EditAttributeActions.js [new file with mode: 0644]
src/editAttributes/EditAttributeConstants.js [new file with mode: 0644]
src/editAttributes/EditAttributeReducer.js [new file with mode: 0644]
src/editAttributes/EditAttributes.jsx [new file with mode: 0644]
src/editAttributes/changeAttributeForm/ChangeAttributeForm.jsx [new file with mode: 0644]
src/editAttributes/changeAttributeForm/ChangeAttributeFormConstants.js [new file with mode: 0644]
src/editAttributes/changeAttributeForm/ChangeAttributeFormReducer.js [new file with mode: 0644]
src/editAttributes/changeAttributeForm/validate.js [new file with mode: 0644]
src/editAttributes/index.html [new file with mode: 0644]
src/editAttributes/main.app.jsx [new file with mode: 0644]
src/editAttributes/networking/NetworkCalls.js [new file with mode: 0644]
src/editAttributes/networking/NetworkConstants.js [new file with mode: 0644]
src/editAttributes/networking/NetworkUtils.js [new file with mode: 0644]
src/generic-components/autoCompleteSearchBar/AutoCompleteSearchBar.jsx
src/generic-components/dynamicViewLoader/DynamicViewLoaderReducer.js
src/generic-components/filterBar/FilterBarConstants.js [new file with mode: 0644]
src/generic-components/filterBar/FilterBarUtils.js [new file with mode: 0644]
src/generic-components/graph/ForceDirectedGraph.jsx
src/generic-components/graph/NodeFactory.js
src/generic-components/graph/NodeVisualElementConstants.js
src/generic-components/graph/TempCreateAttributes.js [new file with mode: 0644]
src/generic-components/treeNode/TreeNode.jsx [new file with mode: 0644]
src/index.html
src/utils/Crypto.js [new file with mode: 0644]
src/utils/DateTimeChartUtil.js
src/utils/Routes.js

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