SDNR align ODLUX 91/89591/1
authorHerbert Eiselt <herbert.eiselt@highstreet-technologies.com>
Fri, 7 Jun 2019 15:55:16 +0000 (17:55 +0200)
committerHerbert Eiselt <herbert.eiselt@highstreet-technologies.com>
Fri, 7 Jun 2019 15:58:18 +0000 (17:58 +0200)
Add missing chart view to UX Performance app

Issue-ID: SDNC-790
Signed-off-by: Herbert Eiselt <herbert.eiselt@highstreet-technologies.com>
Change-Id: I6f5af1e01d2246927b8d05f826f629c7dd5f59a5
Signed-off-by: Herbert Eiselt <herbert.eiselt@highstreet-technologies.com>
36 files changed:
sdnr/wt/odlux/apps/connectApp/src/plugin.tsx
sdnr/wt/odlux/apps/performanceHistoryApp/package.json
sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/connectedNetworkElementsActions.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/connectedNetworkElementsActionHandler.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperature15minHandler.ts [moved from sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/temperature15minHandler.tsx with 100% similarity]
sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPower15minHandler.ts [moved from sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/transmissionPower15minHandler.tsx with 100% similarity]
sdnr/wt/odlux/apps/performanceHistoryApp/src/index.html
sdnr/wt/odlux/apps/performanceHistoryApp/src/models/adaptiveModulationDataType.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/models/availableLtps.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts [new file with mode: 0644]
sdnr/wt/odlux/apps/performanceHistoryApp/src/models/connectedNetworkElements.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/models/crossPolarDiscriminationDataType.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/models/performanceDataType.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/models/receiveLevelDataType.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/models/signalToInteferenceDataType.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/models/temperatureDataType.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/models/transmissionPowerDataType.ts
sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts [new file with mode: 0644]
sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.tsx [deleted file]
sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx [new file with mode: 0644]
sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts [new file with mode: 0644]
sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
sdnr/wt/odlux/framework/pom.xml
sdnr/wt/odlux/framework/src/handlers/authenticationHandler.ts
sdnr/wt/odlux/framework/src/services/applicationApi.ts
sdnr/wt/odlux/yarn.lock

index c9c1182..6ab4be1 100644 (file)
@@ -31,7 +31,13 @@ export function register() {
     menuEntry: "Connect"
   });
 
-  applicationApi.applicationStoreInitialized.then(applicationStore => { applicationStore.dispatch(loadAllMountedNetworkElementsAsync); });
+  const updateAllMountedNetworkElements = () => {
+    applicationApi.applicationStoreInitialized.then(applicationStore => { applicationStore.dispatch(loadAllMountedNetworkElementsAsync); })
+  };
+
+  applicationApi.loginEvent.addHandler(updateAllMountedNetworkElements);
+  updateAllMountedNetworkElements();
+
   // subscribe to the websocket notifications
   subscribe<ObjectNotification & IFormatedMessage>(["ObjectCreationNotification", "ObjectDeletionNotification", "AttributeValueChangedNotification"], (msg => {
     const store = applicationApi.applicationStore;
index 91e0bf3..74b4d9c 100644 (file)
   "author": "Sai Neetha Phulmali",
   "license": "Apache License, Version 2.0",
   "dependencies": {
-    "@odlux/framework" : "*"
+    "@odlux/framework" : "*",
+    "@odlux/connect-app": "*",
+    "react-chartjs-2":"2.7.6",
+    "chart.js":"2.8.0"
   },
   "peerDependencies": {
      "@types/react": "16.4.14",
index 0906584..8f7e99c 100644 (file)
@@ -1,8 +1,8 @@
 import { Action } from '../../../../framework/src/flux/action';
 import { Dispatch } from '../../../../framework/src/flux/store';
+import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
 
-import { ConnectedNetworkElements } from '../models/connectedNetworkElements';
-import { PerformanceHistoryService } from '../services/performanceHistoryService';
+import { ConnectedNetworkElementIds } from '../models/connectedNetworkElements';
 
 /** 
  * Represents the base action. 
@@ -10,32 +10,41 @@ import { PerformanceHistoryService } from '../services/performanceHistoryService
 export class BaseAction extends Action { }
 
 /** 
- * Represents an action causing the store to load all connected network elements. 
+ * Represents an action causing the store to load all connected network element Ids. 
  */
 export class LoadAllConnectedNetworkElementsAction extends BaseAction { }
 
 /** 
- * Represents an action causing the store to update all connected network elements. 
+ * Represents an action causing the store to update all connected network element Ids. 
  */
-export class AllConnectedNetworkElementsLoadedAction extends BaseAction {  
+export class AllConnectedNetworkElementsLoadedAction extends BaseAction {
   /**
    * Initialize this instance.
    * 
-   * @param connectedNetworkElements The network elements which are returned from the restconf.
+   * @param connectedNetworkElements The connected network element Ids which are loaded from the state of connectApp.
    */
-  constructor(public connectedNetworkElements: ConnectedNetworkElements[] | null, public error?: string) {
+  constructor(public connectedNetworkElementIds: ConnectedNetworkElementIds[] | null, public error?: string) {
     super();
   }
 }
 
 /** 
- * Represents an asynchronous thunk  action to load all connected network elements from the restconf
+ * Represents an asynchronous thunk  action to load all connected network element Ids
  */
-export const loadAllConnectedNetworkElementsAsync = (dispatch: Dispatch) => {
-  dispatch(new LoadAllConnectedNetworkElementsAction());
-  PerformanceHistoryService.getConnectedNetworkElementsList().then(networkElements => {
-    networkElements && dispatch(new AllConnectedNetworkElementsLoadedAction(networkElements));
-  }).catch(error => {
-    dispatch(new AllConnectedNetworkElementsLoadedAction(null, error));
-  });
+export const loadAllConnectedNetworkElementsAsync = (dispatch: Dispatch, getState: () => IApplicationStoreState) => {
+    dispatch(new LoadAllConnectedNetworkElementsAction());
+    const connectedNetworkElementsIds = getState().connect.mountedNetworkElements;
+    let mountIdList: ConnectedNetworkElementIds[] = [];
+    connectedNetworkElementsIds.elements.forEach(element => {
+      const connectedNetworkElement = {
+        mountId: element.mountId
+      }
+      mountIdList.push(connectedNetworkElement);
+    });
+    mountIdList.sort((a, b) => {
+      if (a.mountId < b.mountId) return -1;
+      if (a.mountId > b.mountId) return 1;
+      return 0;
+    });
+    dispatch(new AllConnectedNetworkElementsLoadedAction(mountIdList));
 };
\ No newline at end of file
index d8842ff..577066c 100644 (file)
@@ -1,7 +1,7 @@
 import { Action } from '../../../../framework/src/flux/action';
 import { Dispatch } from '../../../../framework/src/flux/store';
 
-import { Ltp } from '../models/availableLtps';
+import { LtpIds } from '../models/availableLtps';
 import { PerformanceHistoryService } from '../services/performanceHistoryService';
 
 /** 
@@ -22,7 +22,7 @@ export class AllAvailableLtpsLoadedAction extends BaseAction {
    * Initialize this instance.
    * @param availableLtps The available ltps which are returned from the database.
    */
-  constructor(public availableLtps: Ltp[] | null, public error?: string) {
+  constructor(public availableLtps: LtpIds[] | null, public error?: string) {
     super();
   }
 }
@@ -37,39 +37,25 @@ export class AllAvailableLtpsLoadedAction extends BaseAction {
  * @param resetLtp The function to verify if the selected ltp is also available in the selected time period database else reset the Ltp dropdown to select.
  */
 export const loadDistinctLtpsbyNetworkElementAsync = (networkElement: string, selectedTimePeriod: string, selectedLtp: string, selectFirstLtp?: Function, resetLtp?: Function) => (dispatch: Dispatch) => {
-  if (selectedTimePeriod == "15min") {
-    dispatch(new LoadAllAvailableLtpsAction());
-    PerformanceHistoryService.getDistinctLtpsFrom15minDatabase(networkElement).then(distinctLtps => {
-      if(distinctLtps) {
-        let ltpNotSelected: boolean = true;
-        selectFirstLtp && selectFirstLtp(distinctLtps[0].key);
-        distinctLtps.forEach((value: Ltp) => {
-          if(value.key === selectedLtp) {
-            ltpNotSelected = false;
-          }
-        });
-        resetLtp && resetLtp(ltpNotSelected);
-        dispatch(new AllAvailableLtpsLoadedAction(distinctLtps))
-      }
-    }).catch(error => {
-      dispatch(new AllAvailableLtpsLoadedAction(null, error));
-    });
-  } else {
-    dispatch(new LoadAllAvailableLtpsAction());
-    PerformanceHistoryService.getDistinctLtpsFrom24hoursDatabase(networkElement).then(distinctLtps => {
-      if(distinctLtps) {
-        let ltpNotSelected: boolean = true;
-        selectFirstLtp && selectFirstLtp(distinctLtps[0].key);
-        distinctLtps.forEach((value: Ltp) => {
-          if(value.key === selectedLtp) {
-            ltpNotSelected = false;
-          }
-        });
-        resetLtp && resetLtp(ltpNotSelected);
-        dispatch(new AllAvailableLtpsLoadedAction(distinctLtps))
-      }
-    }).catch(error => {
-      dispatch(new AllAvailableLtpsLoadedAction(null, error));
-    });
-  }
-};
\ No newline at end of file
+  dispatch(new LoadAllAvailableLtpsAction());
+  PerformanceHistoryService.getDistinctLtpsFromDatabase(networkElement, selectedTimePeriod).then(distinctLtps => {
+    if (distinctLtps) {
+      const ltps = getDistinctLtps(distinctLtps, selectedLtp, selectFirstLtp, resetLtp);
+      dispatch(new AllAvailableLtpsLoadedAction(ltps));
+    }
+  }).catch(error => {
+    dispatch(new AllAvailableLtpsLoadedAction(null, error));
+  });
+};
+
+const getDistinctLtps = (distinctLtps: LtpIds[], selectedLtp: string, selectFirstLtp?: Function, resetLtp?: Function) => {
+  let ltpNotSelected: boolean = true;
+  selectFirstLtp && selectFirstLtp(distinctLtps[0].key);
+  distinctLtps.forEach((value: LtpIds) => {
+    if (value.key === selectedLtp) {
+      ltpNotSelected = false;
+    }
+  });
+  resetLtp && resetLtp(ltpNotSelected);
+  return distinctLtps;
+}
\ No newline at end of file
index 024315c..281ee2f 100644 (file)
@@ -2,23 +2,25 @@ import * as React from 'react';
 
 import { withRouter, RouteComponentProps } from 'react-router-dom';
 
-import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
 import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
 
 import { AdaptiveModulationDataType } from '../models/adaptiveModulationDataType';
-import { createAdaptiveModulation15minProperties, createAdaptiveModulation15minActions, adaptiveModulation15minReloadAction } from '../handlers/adaptiveModulation15minHandler';
-import { createAdaptiveModulation24hoursProperties, createAdaptiveModulation24hoursActions, adaptiveModulation24hoursReloadAction } from '../handlers/adaptiveModulation24hoursHandler';
-
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createAdaptiveModulation15minProperties, createAdaptiveModulation15minActions } from '../handlers/adaptiveModulation15minHandler';
+import { createAdaptiveModulation24hoursProperties, createAdaptiveModulation24hoursActions } from '../handlers/adaptiveModulation24hoursHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
 
 const mapProps = (state: IApplicationStoreState) => ({
   adaptiveModulation15minProperties: createAdaptiveModulation15minProperties(state),
-  adaptiveModulation24hoursProperties: createAdaptiveModulation24hoursProperties(state),
+  adaptiveModulation24hoursProperties: createAdaptiveModulation24hoursProperties(state)
 });
 
 const mapDisp = (dispatcher: IDispatcher) => ({
   adaptiveModulation15minActions: createAdaptiveModulation15minActions(dispatcher.dispatch),
-  adaptiveModulation24hoursActions: createAdaptiveModulation24hoursActions(dispatcher.dispatch),
+  adaptiveModulation24hoursActions: createAdaptiveModulation24hoursActions(dispatcher.dispatch)
 });
 
 type AdaptiveModulationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -32,109 +34,391 @@ const AdaptiveModulationTable = MaterialTable as MaterialTableCtorType<AdaptiveM
  */
 class AdaptiveModulationComponent extends React.Component<AdaptiveModulationComponentProps>{
   render(): JSX.Element {
-    if (this.props.selectedTimePeriod == "15min") {
-      return (
-        <AdaptiveModulationTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "time2-states-s", title: "QAM2S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time2-states", title: "QAM2", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time2-states-l", title: "QAM2L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4-states-s", title: "QAM4S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4-states", title: "QAM4", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4-states-l", title: "QAM4L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time16-states-s", title: "QAM16S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time16-states", title: "QAM16", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time16-states-l", title: "QAM16L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time32-states-s", title: "QAM32S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time32-states", title: "QAM32", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time32-states-l", title: "QAM32L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time64-states-s", title: "QAM64S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time64-states", title: "QAM64", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time64-states-l", title: "QAM64L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time128-states-s", title: "QAM128S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time128-states", title: "QAM128", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time128-states-l", title: "QAM128L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time256-states-s", title: "QAM256S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time256-states", title: "QAM256", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time256-states-l", title: "QAM256L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time512-states-s", title: "QAM512S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time512-states", title: "QAM512", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time512-states-l", title: "QAM512L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time1024-states-s", title: "QAM1024S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time1024-states", title: "QAM1024", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time1024-states-l", title: "QAM1024L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time2048-states-s", title: "QAM2048S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time2048-states", title: "QAM2048", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time2048-states-l", title: "QAM2048L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4096-states-s", title: "QAM4096S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4096-states", title: "QAM4096", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4096-states-l", title: "QAM4096L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time8192-states-s", title: "QAM8192S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time8192-states", title: "QAM8192", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time8192-states-l", title: "QAM8192L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.adaptiveModulation15minProperties} {...this.props.adaptiveModulation15minActions} />
-      );
-    } else {
-      return (
-        <AdaptiveModulationTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "time2-states-s", title: "QAM2S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time2-states", title: "QAM2", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time2-states-l", title: "QAM2L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4-states-s", title: "QAM4S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4-states", title: "QAM4", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4-states-l", title: "QAM4L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time16-states-s", title: "QAM16S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time16-states", title: "QAM16", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time16-states-l", title: "QAM16L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time32-states-s", title: "QAM32S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time32-states", title: "QAM32", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time32-states-l", title: "QAM32L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time64-states-s", title: "QAM64S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time64-states", title: "QAM64", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time64-states-l", title: "QAM64L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time128-states-s", title: "QAM128S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time128-states", title: "QAM128", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time128-states-l", title: "QAM128L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time256-states-s", title: "QAM256S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time256-states", title: "QAM256", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time256-states-l", title: "QAM256L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time512-states-s", title: "QAM512S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time512-states", title: "QAM512", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time512-states-l", title: "QAM512L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time1024-states-s", title: "QAM1024S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time1024-states", title: "QAM1024", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time1024-states-l", title: "QAM1024L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time2048-states-s", title: "QAM2048S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time2048-states", title: "QAM2048", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time2048-states-l", title: "QAM2048L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4096-states-s", title: "QAM4096S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4096-states", title: "QAM4096", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time4096-states-l", title: "QAM4096L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time8192-states-s", title: "QAM8192S", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time8192-states", title: "QAM8192", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "time8192-states-l", title: "QAM8192L", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.adaptiveModulation24hoursProperties} {...this.props.adaptiveModulation24hoursActions} />
-      );
-    }
+    const properties = this.props.selectedTimePeriod === "15min"
+      ? this.props.adaptiveModulation15minProperties
+      : this.props.adaptiveModulation24hoursProperties;
+
+    const actions = this.props.selectedTimePeriod === "15min"
+      ? this.props.adaptiveModulation15minActions
+      : this.props.adaptiveModulation24hoursActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+    const adaptiveModulationColumns: ColumnModel<AdaptiveModulationDataType>[] = [
+      { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
+      { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
+      { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
+      {
+        property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
+          const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
+          return <div >{suspectIntervalFlag} </div>
+        }
+      }];
+
+    chartPagedData.datasets.forEach(ds => {
+      adaptiveModulationColumns.push(addColumnLabels<AdaptiveModulationDataType>(ds.name, ds.columnLabel));
+    });
+
+    return (
+      <>
+        {lineChart(chartPagedData)}
+        <AdaptiveModulationTable idProperty={"_id"} columns={adaptiveModulationColumns} {...properties} {...actions} />
+      </>
+    );
   };
-}
 
-export const AdaptiveModulation = withRouter(connect(mapProps, mapDisp)(AdaptiveModulationComponent));
+  /**
+   * This function gets the performance values for Adaptive modulation according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+
+  private getChartDataValues = (rows: AdaptiveModulationDataType[]): IDataSetsObject => {
+    const _rows = [...rows];
+    sortDataByTimeStamp(_rows);
+
+    const datasets: IDataSet[] = [{
+      name: "time2-states-s",
+      label: "QAM2S",
+      borderColor: '#62a309fc',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM2S",
+    }, {
+      name: "time2-states",
+      label: "QAM2",
+      borderColor: '#62a309fc',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM2",
+    }, {
+      name: "time2-states-l",
+      label: "QAM2L",
+      borderColor: '#62a309fc',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM2L",
+    }, {
+      name: "time4-states-s",
+      label: "QAM4S",
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM4S",
+    }, {
+      name: "time4-states",
+      label: "QAM4",
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM4",
+    }, {
+      name: "time4-states-l",
+      label: "QAM4L",
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM4L",
+    }, {
+      name: "time16-states-s",
+      label: "QAM16S",
+      borderColor: '#9b15e2',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM16S",
+    }, {
+      name: "time16-states",
+      label: "QAM16",
+      borderColor: '#9b15e2',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM16",
+    }, {
+      name: "time16-states-l",
+      label: "QAM16L",
+      borderColor: '#9b15e2',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM16L",
+    }, {
+      name: "time32-states-s",
+      label: "QAM32S",
+      borderColor: '#2704f5f0',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM32S",
+    }, {
+      name: "time32-states",
+      label: "QAM32",
+      borderColor: '#2704f5f0',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM32",
+    }, {
+      name: "time32-states-l",
+      label: "QAM32L",
+      borderColor: '#2704f5f0',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM32L",
+    }, {
+      name: "time64-states-s",
+      label: "QAM64S",
+      borderColor: '#347692',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM64S",
+    }, {
+      name: "time64-states",
+      label: "QAM64",
+      borderColor: '#347692',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM64",
+    }, {
+      name: "time64-states-l",
+      label: "QAM64L",
+      borderColor: '#347692',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM64L",
+    }, {
+      name: "time128-states-s",
+      label: "QAM128S",
+      borderColor: '#885e22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM128S",
+    }, {
+      name: "time128-states",
+      label: "QAM128",
+      borderColor: '#885e22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM128",
+    }, {
+      name: "time128-states-l",
+      label: "QAM128L",
+      borderColor: '#885e22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM128L",
+    }, {
+      name: "time256-states-s",
+      label: "QAM256S",
+      borderColor: '#de07807a',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM256S",
+    }, {
+      name: "time256-states",
+      label: "QAM256",
+      borderColor: '#de07807a',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM256",
+    }, {
+      name: "time256-states-l",
+      label: "QAM256L",
+      borderColor: '#de07807a',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM256L",
+    }, {
+      name: "time512-states-s",
+      label: "QAM512S",
+      borderColor: '#8fdaacde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM512S",
+    }, {
+      name: "time512-states",
+      label: "QAM512",
+      borderColor: '#8fdaacde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM512",
+    }, {
+
+      name: "time512-states-l",
+      label: "QAM512L",
+      borderColor: '#8fdaacde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM512L",
+    }, {
+
+      name: "time1024-states-s",
+      label: "QAM1024S",
+      borderColor: '#435b22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM1024S",
+    }, {
+
+      name: "time1024-states",
+      label: "QAM1024",
+      borderColor: '#435b22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM1024",
+    }, {
+
+      name: "time1024-states-l",
+      label: "QAM1024L",
+      borderColor: '#435b22',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM1024L",
+    }, {
+      name: "time2048-states-s",
+      label: "QAM2048S",
+      borderColor: '#e87a5b',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM2048S",
+    }, {
+      name: "time2048-states",
+      label: "QAM2048",
+      borderColor: '#e87a5b',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM2048",
+    }, {
+      name: "time2048-states-l",
+      label: "QAM2048L",
+      borderColor: '#e87a5b',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM2048L",
+    }, {
+      name: "time4096-states-s",
+      label: "QAM4096S",
+      borderColor: '#5be878',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM4096S",
+    }, {
+      name: "time4096-states",
+      label: "QAM4096",
+      borderColor: '#5be878',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM4096",
+    }, {
+      name: "time4096-states-l",
+      label: "QAM4096L",
+      borderColor: '#5be878',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM4096L",
+    }, {
+      name: "time8192-states-s",
+      label: "QAM8192s",
+      borderColor: '#cb5be8',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM8192S",
+    }, {
+      name: "time8192-states",
+      label: "QAM8192",
+      borderColor: '#cb5be8',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM8192",
+    }, {
+      name: "time8192-states-l",
+      label: "QAM8192L",
+      borderColor: '#cb5be8',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "QAM8192L",
+    }
+    ];
+
+    _rows.forEach(row => {
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row["time-stamp"],
+          y: row[ds.name as keyof AdaptiveModulationDataType] as string
+        });
+      });
+    });
+
+    return {
+      datasets: datasets
+    };
+  }
+}
+const AdaptiveModulation = withRouter(connect(mapProps, mapDisp)(AdaptiveModulationComponent));
 export default AdaptiveModulation;
index bbed8ab..42e3f93 100644 (file)
@@ -2,23 +2,25 @@ import * as React from 'react';
 
 import { withRouter, RouteComponentProps } from 'react-router-dom';
 
-import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { MaterialTable, ColumnType, MaterialTableCtorType, ColumnModel } from '../../../../framework/src/components/material-table';
 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
 import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
 
 import { CrossPolarDiscriminationDataType } from '../models/crossPolarDiscriminationDataType';
-import { createCrossPolarDiscrimination15minProperties, createCrossPolarDiscrimination15minActions, crossPolarDiscrimination15minReloadAction } from '../handlers/crossPolarDiscrimination15minHandler';
-import { createCrossPolarDiscrimination24hoursProperties, createCrossPolarDiscrimination24hoursActions, crossPolarDiscrimination24hoursReloadAction } from '../handlers/crossPolarDiscrimination24hoursHandler';
-
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createCrossPolarDiscrimination15minProperties, createCrossPolarDiscrimination15minActions } from '../handlers/crossPolarDiscrimination15minHandler';
+import { createCrossPolarDiscrimination24hoursProperties, createCrossPolarDiscrimination24hoursActions } from '../handlers/crossPolarDiscrimination24hoursHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
 
 const mapProps = (state: IApplicationStoreState) => ({
   crossPolarDiscrimination15minProperties: createCrossPolarDiscrimination15minProperties(state),
-  crossPolarDiscrimination24hoursProperties: createCrossPolarDiscrimination24hoursProperties(state),
+  crossPolarDiscrimination24hoursProperties: createCrossPolarDiscrimination24hoursProperties(state)
 });
 
 const mapDisp = (dispatcher: IDispatcher) => ({
   crossPolarDiscrimination15minActions: createCrossPolarDiscrimination15minActions(dispatcher.dispatch),
-  crossPolarDiscrimination24hoursActions: createCrossPolarDiscrimination24hoursActions(dispatcher.dispatch),
+  crossPolarDiscrimination24hoursActions: createCrossPolarDiscrimination24hoursActions(dispatcher.dispatch)
 });
 
 type CrossPolarDiscriminationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -32,43 +34,87 @@ const CrossPolarDiscriminationTable = MaterialTable as MaterialTableCtorType<Cro
  */
 class CrossPolarDiscriminationComponent extends React.Component<CrossPolarDiscriminationComponentProps>{
   render(): JSX.Element {
-    if (this.props.selectedTimePeriod == "15min") {
-      return (
-        <CrossPolarDiscriminationTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "xpd-min", title: "CPD (min)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "xpd-avg", title: "CPD (avg)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "xpd-max", title: "CPD (max)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.crossPolarDiscrimination15minProperties} {...this.props.crossPolarDiscrimination15minActions} />
-      );
-    } else {
-      return (
-        <CrossPolarDiscriminationTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "xpd-min", title: "CPD (min)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "xpd-avg", title: "CPD (avg)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "xpd-max", title: "CPD (max)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.crossPolarDiscrimination24hoursProperties} {...this.props.crossPolarDiscrimination24hoursActions} />
-      );
-    }
+    const properties = this.props.selectedTimePeriod === "15min"
+      ? this.props.crossPolarDiscrimination15minProperties
+      : this.props.crossPolarDiscrimination24hoursProperties;
+    const actions = this.props.selectedTimePeriod === "15min"
+      ? this.props.crossPolarDiscrimination15minActions
+      : this.props.crossPolarDiscrimination24hoursActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+
+    const cpdColumns: ColumnModel<CrossPolarDiscriminationDataType>[] = [
+      { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
+      { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
+      { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
+      {
+        property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
+          const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
+          return <div >{suspectIntervalFlag} </div>
+        }
+      }
+    ];
+    
+    chartPagedData.datasets.forEach(ds => {
+      cpdColumns.push(addColumnLabels<CrossPolarDiscriminationDataType>(ds.name, ds.columnLabel));
+    });
+    return (
+      <>
+        {lineChart(chartPagedData)}
+        <CrossPolarDiscriminationTable idProperty={"_id"} columns={cpdColumns} {...properties} {...actions} />
+      </>
+    );
   };
-}
 
-export const CrossPolarDiscrimination = withRouter(connect(mapProps, mapDisp)(CrossPolarDiscriminationComponent));
+  /**
+   * This function gets the performance values for CPD according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+  private getChartDataValues = (rows: CrossPolarDiscriminationDataType[]): IDataSetsObject => {
+    const _rows = [...rows];
+    sortDataByTimeStamp(_rows);
+
+    const datasets: IDataSet[] = [{
+      name: "xpd-min",
+      label: "xpd-min",
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "CPD (min)[db]"
+    }, {
+      name: "xpd-avg",
+      label: "xpd-avg",
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "CPD (avg)[db]"
+    }, {
+      name: "xpd-max",
+      label: "xpd-max",
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "CPD (max)[db]"
+    }];
+
+    _rows.forEach(row => {
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row["time-stamp"],
+          y: row[ds.name as keyof CrossPolarDiscriminationDataType] as string
+        });
+      });
+    });
+    return {
+      datasets: datasets
+    };
+  }
+}
+const CrossPolarDiscrimination = withRouter(connect(mapProps, mapDisp)(CrossPolarDiscriminationComponent));
 export default CrossPolarDiscrimination;
index e9a373b..578022d 100644 (file)
@@ -2,22 +2,24 @@ import * as React from 'react';
 
 import { withRouter, RouteComponentProps } from 'react-router-dom';
 
-import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
 import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-
 import { PerformanceDataType } from '../models/performanceDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
 import { createPerformanceData15minProperties, createPerformanceData15minActions } from '../handlers/performanceData15minHandler';
 import { createPerformanceData24hoursProperties, createPerformanceData24hoursActions } from '../handlers/performanceData24hoursHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
 
 const mapProps = (state: IApplicationStoreState) => ({
   performanceData15minProperties: createPerformanceData15minProperties(state),
-  performanceData24hoursProperties: createPerformanceData24hoursProperties(state),
+  performanceData24hoursProperties: createPerformanceData24hoursProperties(state)
 });
 
 const mapDisp = (dispatcher: IDispatcher) => ({
   performanceData15minActions: createPerformanceData15minActions(dispatcher.dispatch),
-  performanceData24hoursActions: createPerformanceData24hoursActions(dispatcher.dispatch),
+  performanceData24hoursActions: createPerformanceData24hoursActions(dispatcher.dispatch)
 });
 
 type PerformanceDataComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -31,45 +33,87 @@ const PerformanceDataTable = MaterialTable as MaterialTableCtorType<PerformanceD
  */
 class PerformanceDataComponent extends React.Component<PerformanceDataComponentProps>{
   render(): JSX.Element {
-    if (this.props.selectedTimePeriod == "15min") {
-      return (
-        <PerformanceDataTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "es", title: "ES", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "ses", title: "SES", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "unavailability", title: "UAS", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.performanceData15minProperties} {...this.props.performanceData15minActions}
-        />
-      );
-    } else {
-      return (
-        <PerformanceDataTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "es", title: "ES", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "ses", title: "SES", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "unavailability", title: "UAS", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.performanceData24hoursProperties} {...this.props.performanceData24hoursActions}
-        />
-      );
-    }
+    const properties = this.props.selectedTimePeriod === "15min"
+      ? this.props.performanceData15minProperties
+      : this.props.performanceData24hoursProperties;
+    const actions = this.props.selectedTimePeriod === "15min"
+      ? this.props.performanceData15minActions
+      : this.props.performanceData24hoursActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+    const performanceColumns: ColumnModel<PerformanceDataType>[] = [
+      { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
+      { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
+      { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
+      {
+        property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
+          const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
+          return <div >{suspectIntervalFlag} </div>
+        }
+      }
+    ];
+
+    chartPagedData.datasets.forEach(ds => {
+      performanceColumns.push(addColumnLabels<PerformanceDataType>(ds.name, ds.columnLabel));
+    });
+    return (
+      <>
+        {lineChart(chartPagedData)}
+        <PerformanceDataTable idProperty={"_id"} columns={performanceColumns} {...properties} {...actions} />
+      </>
+    );
   };
+
+  /**
+   * This function gets the performance values for PerformanceData according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+  private getChartDataValues = (rows: PerformanceDataType[]): IDataSetsObject => {
+    const _rows = [...rows];
+    sortDataByTimeStamp(_rows);
+
+    const datasets: IDataSet[] = [{
+      name: "es",
+      label: "es",
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "ES"
+    }, {
+      name: "ses",
+      label: "ses",
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "SES"
+    }, {
+      name: "unavailability",
+      label: "unavailability",
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "Unavailability"
+    }];
+
+    _rows.forEach(row => {
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row["time-stamp"],
+          y: row[ds.name as keyof PerformanceDataType] as string
+        });
+      });
+    });
+    return {
+      datasets: datasets
+    };
+  }
 }
 
-export const PerformanceData = withRouter(connect(mapProps, mapDisp)(PerformanceDataComponent));
+const PerformanceData = withRouter(connect(mapProps, mapDisp)(PerformanceDataComponent));
 export default PerformanceData;
index 5f62e58..b893ce1 100644 (file)
@@ -2,23 +2,25 @@ import * as React from 'react';
 
 import { withRouter, RouteComponentProps } from 'react-router-dom';
 
-import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
 import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
 
 import { ReceiveLevelDataType } from '../models/receiveLevelDataType';
-import { createReceiveLevel15minProperties, createReceiveLevel15minActions, receiveLevel15minReloadAction } from '../handlers/receiveLevel15minHandler';
-import { createReceiveLevel24hoursProperties, createReceiveLevel24hoursActions, receiveLevel24hoursReloadAction } from '../handlers/receiveLevel24hoursHandler';
-
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createReceiveLevel15minProperties, createReceiveLevel15minActions } from '../handlers/receiveLevel15minHandler';
+import { createReceiveLevel24hoursProperties, createReceiveLevel24hoursActions } from '../handlers/receiveLevel24hoursHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
 
 const mapProps = (state: IApplicationStoreState) => ({
   receiveLevel15minProperties: createReceiveLevel15minProperties(state),
-  receiveLevel24hoursProperties: createReceiveLevel24hoursProperties(state),
+  receiveLevel24hoursProperties: createReceiveLevel24hoursProperties(state)
 });
 
 const mapDisp = (dispatcher: IDispatcher) => ({
   receiveLevel15minActions: createReceiveLevel15minActions(dispatcher.dispatch),
-  receiveLevel24hoursActions: createReceiveLevel24hoursActions(dispatcher.dispatch),
+  receiveLevel24hoursActions: createReceiveLevel24hoursActions(dispatcher.dispatch)
 });
 
 type ReceiveLevelComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -32,43 +34,88 @@ const ReceiveLevelTable = MaterialTable as MaterialTableCtorType<ReceiveLevelDat
  */
 class ReceiveLevelComponent extends React.Component<ReceiveLevelComponentProps>{
   render(): JSX.Element {
-    if (this.props.selectedTimePeriod == "15min") {
-      return (
-        <ReceiveLevelTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "rx-level-min", title: "Rx min", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "rx-level-avg", title: "Rx avg", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "rx-level-max", title: "Rx max", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.receiveLevel15minProperties} {...this.props.receiveLevel15minActions} />
-      );
-    } else {
-      return (
-        <ReceiveLevelTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "rx-level-min", title: "Rx min", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "rx-level-avg", title: "Rx avg", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "rx-level-max", title: "Rx max", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.receiveLevel24hoursProperties} {...this.props.receiveLevel24hoursActions} />
-      );
-    }
+    const properties = this.props.selectedTimePeriod === "15min"
+      ? this.props.receiveLevel15minProperties
+      : this.props.receiveLevel24hoursProperties;
+    const actions = this.props.selectedTimePeriod === "15min"
+      ? this.props.receiveLevel15minActions
+      : this.props.receiveLevel24hoursActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+    const receiveLevelColumns: ColumnModel<ReceiveLevelDataType>[] = [
+      { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
+      { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
+      { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
+      {
+        property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
+          const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
+          return <div >{suspectIntervalFlag} </div>
+        }
+      }
+    ];
+
+    chartPagedData.datasets.forEach(ds => {
+      receiveLevelColumns.push(addColumnLabels<ReceiveLevelDataType>(ds.name, ds.columnLabel));
+    });
+
+    return (
+      <>
+        {lineChart(chartPagedData)}
+        <ReceiveLevelTable idProperty={"_id"} columns={receiveLevelColumns} {...properties} {...actions} />
+      </>
+    );
   };
+
+  /**
+   * This function gets the performance values for ReceiveLevel according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+  private getChartDataValues = (rows: ReceiveLevelDataType[]): IDataSetsObject => {
+    const _rows = [...rows];
+    sortDataByTimeStamp(_rows);
+
+    const datasets: IDataSet[] = [{
+      name: "rx-level-min",
+      label: "rx-level-min",
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "Rx min"
+    }, {
+      name: "rx-level-avg",
+      label: "rx-level-avg",
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "Rx avg"
+    }, {
+      name: "rx-level-max",
+      label: "rx-level-max",
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "Rx max"
+    }];
+
+    _rows.forEach(row => {
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row["time-stamp"],
+          y: row[ds.name as keyof ReceiveLevelDataType] as string
+        });
+      });
+    });
+    return {
+      datasets: datasets
+    };
+  }
 }
 
-export const ReceiveLevel = withRouter(connect(mapProps, mapDisp)(ReceiveLevelComponent));
+const ReceiveLevel = withRouter(connect(mapProps, mapDisp)(ReceiveLevelComponent));
 export default ReceiveLevel;
index bd61282..90ed1a9 100644 (file)
@@ -2,22 +2,25 @@ import * as React from 'react';
 
 import { withRouter, RouteComponentProps } from 'react-router-dom';
 
-import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
 import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
 
 import { SignalToInterferenceDataType } from '../models/signalToInteferenceDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
 import { createSignalToInterference15minProperties, createSignalToInterference15minActions } from '../handlers/signalToInterference15minHandler';
 import { createSignalToInterference24hoursProperties, createSignalToInterference24hoursActions } from '../handlers/signalToInterference24hoursHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
 
 const mapProps = (state: IApplicationStoreState) => ({
   signalToInterference15minProperties: createSignalToInterference15minProperties(state),
-  signalToInterference24hoursProperties: createSignalToInterference24hoursProperties(state),
+  signalToInterference24hoursProperties: createSignalToInterference24hoursProperties(state)
 });
 
 const mapDisp = (dispatcher: IDispatcher) => ({
   signalToInterference15minActions: createSignalToInterference15minActions(dispatcher.dispatch),
-  signalToInterference24hoursActions: createSignalToInterference24hoursActions(dispatcher.dispatch),
+  signalToInterference24hoursActions: createSignalToInterference24hoursActions(dispatcher.dispatch)
 });
 
 type SignalToInterferenceComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -31,45 +34,91 @@ const SignalToInterferenceTable = MaterialTable as MaterialTableCtorType<SignalT
  */
 class SignalToInterferenceComponent extends React.Component<SignalToInterferenceComponentProps>{
   render(): JSX.Element {
-    if (this.props.selectedTimePeriod == "15min") {
-      return (
-        <SignalToInterferenceTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "snir-min", title: "SINR (min)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "snir-avg", title: "SINR (avg)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "snir-max", title: "SINR (max)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.signalToInterference15minProperties} {...this.props.signalToInterference15minActions}
-        />
-      );
-    } else {
-      return (
-        <SignalToInterferenceTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "snir-min", title: "SINR (min)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "snir-avg", title: "SINR (avg)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "snir-max", title: "SINR (max)[db]", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.signalToInterference24hoursProperties} {...this.props.signalToInterference24hoursActions}
+    const properties = this.props.selectedTimePeriod === "15min"
+      ? this.props.signalToInterference15minProperties
+      : this.props.signalToInterference24hoursProperties;
+    const actions = this.props.selectedTimePeriod === "15min"
+      ? this.props.signalToInterference15minActions
+      : this.props.signalToInterference24hoursActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+
+    const sinrColumns: ColumnModel<SignalToInterferenceDataType>[] = [
+
+      { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
+      { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
+      { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
+      {
+        property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
+          const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
+          return <div >{suspectIntervalFlag} </div>
+        }
+      }
+    ];
+    
+    chartPagedData.datasets.forEach(ds => {
+      sinrColumns.push(addColumnLabels<SignalToInterferenceDataType>(ds.name, ds.columnLabel));
+    });
+    return (
+      <>
+        {lineChart(chartPagedData)}
+        <SignalToInterferenceTable idProperty={"_id"} columns={sinrColumns} {...properties} {...actions}
         />
-      );
-    }
+      </>
+    );
   };
+
+  /**
+   * This function gets the performance values for SINR according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+
+  private getChartDataValues = (rows: SignalToInterferenceDataType[]): IDataSetsObject => {
+    const _rows = [...rows];
+    sortDataByTimeStamp(_rows);
+
+    const datasets: IDataSet[] = [{
+      name: "snir-min",
+      label: "snir-min",
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "SINR (min)[db]"
+    }, {
+      name: "snir-avg",
+      label: "snir-avg",
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "SINR (avg)[db]"
+    }, {
+      name: "snir-max",
+      label: "snir-max",
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "SINR (max)[db]"
+    }];
+
+    _rows.forEach(row => {
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row["time-stamp"],
+          y: row[ds.name as keyof SignalToInterferenceDataType] as string
+        });
+      });
+    });
+    return {
+      datasets: datasets
+    };
+  }
 }
 
-export const SignalToInterference = withRouter(connect(mapProps, mapDisp)(SignalToInterferenceComponent));
+const SignalToInterference = withRouter(connect(mapProps, mapDisp)(SignalToInterferenceComponent));
 export default SignalToInterference;
index 1496396..f105bfd 100644 (file)
@@ -2,23 +2,25 @@ import * as React from 'react';
 
 import { withRouter, RouteComponentProps } from 'react-router-dom';
 
-import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
 import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
 
 import { TemperatureDataType } from '../models/temperatureDataType';
-import { createTemperature15minProperties, createTemperature15minActions, temperature15minReloadAction } from '../handlers/temperature15minHandler';
-import { createTemperature24hoursProperties, createTemperature24hoursActions, temperature24hoursReloadAction } from '../handlers/temperature24hoursHandler';
-
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
+import { createTemperature15minProperties, createTemperature15minActions } from '../handlers/temperature15minHandler';
+import { createTemperature24hoursProperties, createTemperature24hoursActions } from '../handlers/temperature24hoursHandler';
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
 
 const mapProps = (state: IApplicationStoreState) => ({
   temperature15minProperties: createTemperature15minProperties(state),
-  temperature24hoursProperties: createTemperature24hoursProperties(state),
+  temperature24hoursProperties: createTemperature24hoursProperties(state)
 });
 
 const mapDisp = (dispatcher: IDispatcher) => ({
   temperature15minActions: createTemperature15minActions(dispatcher.dispatch),
-  temperature24hoursActions: createTemperature24hoursActions(dispatcher.dispatch),
+  temperature24hoursActions: createTemperature24hoursActions(dispatcher.dispatch)
 });
 
 type TemperatureComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -32,43 +34,88 @@ const TemperatureTable = MaterialTable as MaterialTableCtorType<TemperatureDataT
  */
 class TemperatureComponent extends React.Component<TemperatureComponentProps>{
   render(): JSX.Element {
-    if (this.props.selectedTimePeriod == "15min") {
-      return (
-        <TemperatureTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "rf-temp-min", title: "Rx min", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "rf-temp-avg", title: "Rx avg", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "rf-temp-max", title: "Rx max", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.temperature15minProperties} {...this.props.temperature15minActions} />
-      );
-    } else {
-      return (
-        <TemperatureTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "rf-temp-min", title: "Rx min", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "rf-temp-avg", title: "Rx avg", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "rf-temp-max", title: "Rx max", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.temperature24hoursProperties} {...this.props.temperature24hoursActions} />
-      );
-    }
+    const properties = this.props.selectedTimePeriod === "15min"
+      ? this.props.temperature15minProperties
+      : this.props.temperature24hoursProperties;
+    const actions = this.props.selectedTimePeriod === "15min"
+      ? this.props.temperature15minActions
+      : this.props.temperature24hoursActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+    const temperatureColumns: ColumnModel<TemperatureDataType>[] = [
+      { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
+      { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
+      { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
+      {
+        property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
+          const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
+          return <div >{suspectIntervalFlag} </div>
+        }
+      }
+    ];
+    
+    chartPagedData.datasets.forEach(ds => {
+      temperatureColumns.push(addColumnLabels<TemperatureDataType>(ds.name, ds.columnLabel));
+    });
+    return (
+      <>
+        {lineChart(chartPagedData)}
+        <TemperatureTable idProperty={"_id"} columns={temperatureColumns} {...properties} {...actions} />
+      </>
+    );
   };
+
+  /**
+   * This function gets the performance values for Temperature according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+
+  private getChartDataValues = (rows: TemperatureDataType[]): IDataSetsObject => {
+    const _rows = [...rows];
+    sortDataByTimeStamp(_rows);
+
+    const datasets: IDataSet[] = [{
+      name: "rf-temp-min",
+      label: "rf-temp-min",
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "Rf Temp Min[deg C]"
+    }, {
+      name: "rf-temp-avg",
+      label: "rf-temp-avg",
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "Rf Temp Avg[deg C]"
+    }, {
+      name: "rf-temp-max",
+      label: "rf-temp-max",
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "Rf Temp Max[deg C]"
+    }];
+
+    _rows.forEach(row => {
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row["time-stamp"],
+          y: row[ds.name as keyof TemperatureDataType] as string
+        });
+      });
+    });
+    return {
+      datasets: datasets
+    };
+  }
 }
 
-export const Temperature = withRouter(connect(mapProps, mapDisp)(TemperatureComponent));
+const Temperature = withRouter(connect(mapProps, mapDisp)(TemperatureComponent));
 export default Temperature;
index 10c2587..088a83e 100644 (file)
@@ -2,23 +2,25 @@ import * as React from 'react';
 
 import { withRouter, RouteComponentProps } from 'react-router-dom';
 
-import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
 import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
 
 import { TransmissionPowerDataType } from '../models/transmissionPowerDataType';
+import { IDataSet, IDataSetsObject } from '../models/chartTypes';
 import { createTransmissionPower15minProperties, createTransmissionPower15minActions } from '../handlers/transmissionPower15minHandler';
 import { createTransmissionPower24hoursProperties, createTransmissionPower24hoursActions } from '../handlers/transmissionPower24hoursHandler';
-
+import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
+import { addColumnLabels } from '../utils/tableUtils';
 
 const mapProps = (state: IApplicationStoreState) => ({
   transmissionPower15minProperties: createTransmissionPower15minProperties(state),
-  transmissionPower24hoursProperties: createTransmissionPower24hoursProperties(state),
+  transmissionPower24hoursProperties: createTransmissionPower24hoursProperties(state)
 });
 
 const mapDisp = (dispatcher: IDispatcher) => ({
   transmissionPower15minActions: createTransmissionPower15minActions(dispatcher.dispatch),
-  transmissionPower24hoursActions: createTransmissionPower24hoursActions(dispatcher.dispatch),
+  transmissionPower24hoursActions: createTransmissionPower24hoursActions(dispatcher.dispatch)
 });
 
 type TransmissionPowerComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -32,43 +34,90 @@ const TransmissionPowerTable = MaterialTable as MaterialTableCtorType<Transmissi
  */
 class TransmissionPowerComponent extends React.Component<TransmissionPowerComponentProps>{
   render(): JSX.Element {
-    if (this.props.selectedTimePeriod == "15min") {
-      return (
-        <TransmissionPowerTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "tx-level-min", title: "Tx min", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "tx-level-avg", title: "Tx avg", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "tx-level-max", title: "Tx max", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.transmissionPower15minProperties} {...this.props.transmissionPower15minActions} />
-      );
-    } else {
-      return (
-        <TransmissionPowerTable idProperty={"_id"} columns={[
-          { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
-          { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
-          { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
-          {
-            property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
-              const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
-              return <div >{suspectIntervalFlag} </div>
-            }
-          },
-          { property: "tx-level-min", title: "Tx min", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "tx-level-avg", title: "Tx avg", type: ColumnType.text, disableFilter: true, disableSorting: true },
-          { property: "tx-level-max", title: "Tx max", type: ColumnType.text, disableFilter: true, disableSorting: true },
-        ]} {...this.props.transmissionPower24hoursProperties} {...this.props.transmissionPower24hoursActions} />
-      );
-    }
+    const properties = this.props.selectedTimePeriod === "15min"
+      ? this.props.transmissionPower15minProperties
+      : this.props.transmissionPower24hoursProperties;
+    const actions = this.props.selectedTimePeriod === "15min"
+      ? this.props.transmissionPower15minActions
+      : this.props.transmissionPower24hoursActions;
+
+    const chartPagedData = this.getChartDataValues(properties.rows);
+
+    const transmissionColumns: ColumnModel<TransmissionPowerDataType>[] = [
+      { property: "radio-signal-id", title: "Radio signal", type: ColumnType.text },
+      { property: "scanner-id", title: "Scanner ID", type: ColumnType.text },
+      { property: "time-stamp", title: "End Time", type: ColumnType.text, disableFilter: true },
+      {
+        property: "suspect-interval-flag", title: "Suspect Interval", type: ColumnType.custom, customControl: ({ rowData }) => {
+          const suspectIntervalFlag = rowData["suspect-interval-flag"].toString();
+          return <div >{suspectIntervalFlag} </div>
+        }
+      }
+    ];
+    
+    chartPagedData.datasets.forEach(ds => {
+      transmissionColumns.push(addColumnLabels<TransmissionPowerDataType>(ds.name, ds.columnLabel));
+    });
+
+    return (
+      <>
+        {lineChart(chartPagedData)}
+        <TransmissionPowerTable idProperty={"_id"} columns={transmissionColumns} {...properties} {...actions} />
+      </>
+    );
   };
+
+  /**
+   * This function gets the performance values for TransmissionPower according on the chartjs dataset structure 
+   * which is to be sent to the chart.
+   */
+
+  private getChartDataValues = (rows: TransmissionPowerDataType[]): IDataSetsObject => {
+    const _rows = [...rows];
+    sortDataByTimeStamp(_rows);
+
+    const datasets: IDataSet[] = [{
+      name: "tx-level-min",
+      label: "tx-level-min",
+      borderColor: '#0e17f3de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "Tx min"
+    }, {
+      name: "tx-level-avg",
+      label: "tx-level-avg",
+      borderColor: '#08edb6de',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "Tx avg"
+    }, {
+      name: "tx-level-max",
+      label: "tx-level-max",
+      borderColor: '#b308edde',
+      bezierCurve: false,
+      lineTension: 0,
+      fill: false,
+      data: [],
+      columnLabel: "Tx max"
+    }];
+
+    _rows.forEach(row => {
+      datasets.forEach(ds => {
+        ds.data.push({
+          x: row["time-stamp"],
+          y: row[ds.name as keyof TransmissionPowerDataType] as string
+        });
+      });
+    });
+    return {
+      datasets: datasets
+    };
+  }
 }
 
-export const TransmissionPower = withRouter(connect(mapProps, mapDisp)(TransmissionPowerComponent));
+const TransmissionPower = withRouter(connect(mapProps, mapDisp)(TransmissionPowerComponent));
 export default TransmissionPower;
index 2fd0ac8..415b073 100644 (file)
@@ -5,10 +5,10 @@ import {
   LoadAllAvailableLtpsAction,
 } from '../actions/ltpAction';
 
-import { Ltp } from '../models/availableLtps';
+import { LtpIds } from '../models/availableLtps';
 
 export interface IAvailableLtpsState {
-  distinctLtps: Ltp[];
+  distinctLtps: LtpIds[];
   busy: boolean;
 }
 
index 039ae53..ad153f0 100644 (file)
@@ -1,19 +1,15 @@
 import { IActionHandler } from '../../../../framework/src/flux/action';
 
-import {
-  AllConnectedNetworkElementsLoadedAction,
-  LoadAllConnectedNetworkElementsAction,
-} from '../actions/connectedNetworkElementsActions';
-
-import { ConnectedNetworkElements } from '../models/connectedNetworkElements';
+import { AllConnectedNetworkElementsLoadedAction, LoadAllConnectedNetworkElementsAction } from '../actions/connectedNetworkElementsActions';
+import { ConnectedNetworkElementIds } from '../models/connectedNetworkElements';
 
 export interface IConnectedNetworkElementsState {
-  connectedNetworkElements: ConnectedNetworkElements[];
+  connectedNetworkElementIds: ConnectedNetworkElementIds[];
   busy: boolean;
 }
 
 const connectedNetworkElementsStateInit: IConnectedNetworkElementsState = {
-  connectedNetworkElements: [],
+  connectedNetworkElementIds: [],
   busy: false
 };
 
@@ -26,10 +22,10 @@ export const connectedNetworkElementsActionHandler: IActionHandler<IConnectedNet
     };
 
   } else if (action instanceof AllConnectedNetworkElementsLoadedAction) {
-    if (!action.error && action.connectedNetworkElements) {
+    if (!action.error && action.connectedNetworkElementIds) {
       state = {
         ...state,
-        connectedNetworkElements: action.connectedNetworkElements,
+        connectedNetworkElementIds: action.connectedNetworkElementIds,
         busy: false
       };
     } else {
index 1cf814b..43813e5 100644 (file)
@@ -6,6 +6,7 @@ import { combineActionHandler } from '../../../../framework/src/flux/middleware'
 import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
 import { IActionHandler } from '../../../../framework/src/flux/action';
 
+import { IConnectAppStoreState } from '../../../connectApp/src/handlers/connectAppRootHandler';
 import { IPerformanceData15minState, performanceData15minActionHandler } from './performanceData15minHandler';
 import { IReceiveLevel15minState, receiveLevel15minActionHandler } from './receiveLevel15minHandler';
 import { ITransmissionPower15minState, transmissionPower15minActionHandler } from './transmissionPower15minHandler';
@@ -55,6 +56,7 @@ const currentOpenPanelHandler: IActionHandler<string | null> = (state = null, ac
 declare module '../../../../framework/src/store/applicationStore' {
   interface IApplicationStoreState {
     performanceHistory: IPerformanceHistoryStoreState;
+    connect: IConnectAppStoreState;
   }
 }
 
@@ -75,9 +77,9 @@ const actionHandlers = {
   signalToInterference24hours: signalToInterference24hoursActionHandler,
   crossPolarDiscrimination15min: crossPolarDiscrimination15minActionHandler,
   crossPolarDiscrimination24hours: crossPolarDiscrimination24hoursActionHandler,
-  currentOpenPanel: currentOpenPanelHandler,
+  currentOpenPanel: currentOpenPanelHandler
 };
 
-export const performanceHistoryRootHandler = combineActionHandler<IPerformanceHistoryStoreState>(actionHandlers);
+const performanceHistoryRootHandler = combineActionHandler<IPerformanceHistoryStoreState>(actionHandlers);
 export default performanceHistoryRootHandler;
 
index fce395d..8cb775b 100644 (file)
@@ -5,7 +5,7 @@
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
-  <link rel="stylesheet" href="./vendor.css" >
+  <!-- <link rel="stylesheet" href="./vendor.css" > -->
   <title>PM History Application</title>
 </head>
 
@@ -15,7 +15,8 @@
   <script type="text/javascript" src="./config.js"></script>
   <script>
     // run the application
-    require(["app","performanceHistoryApp"], function (app, performanceHistoryApp) {
+    require(["app", "connectApp", "performanceHistoryApp"], function (app, connectApp, performanceHistoryApp) {
+      connectApp.register();
       performanceHistoryApp.register();
       app("./app.tsx").runApplication();
     });
index 686e3bc..701d54a 100644 (file)
@@ -47,7 +47,6 @@ export type AdaptiveModulationDataType = {
   "time8192-states-l": string;
 };
 
-
 export type AdaptiveModulationResult = { "performance-data": AdaptiveModulationDataType };
 
-export type AdaptiveModulation = AdaptiveModulationDataType & { _id: string };
\ No newline at end of file
+export type AdaptiveModulation = AdaptiveModulationDataType & { _id: string };
index 15a27f1..d5a6c68 100644 (file)
@@ -1,14 +1,14 @@
-  export type Ltp = {
+  export type LtpIds = {
     key: string
   }
 
-  export type Bucket={ 
-    buckets: Ltp[]
+  export type Bucket<T>={ 
+    buckets: T[]
   }
 
 /**
  * Represents distinct available ltps using elasticsearch aggregations structure.
  */
   export type DistinctLtp = {
-    "uuid-interface": Bucket
+    "uuid-interface": Bucket<LtpIds>
   }
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/chartTypes.ts
new file mode 100644 (file)
index 0000000..8ea59e2
--- /dev/null
@@ -0,0 +1,33 @@
+export interface IData  {
+  x: string;
+  y: string;
+}
+  
+/**
+ * Structure of chartjs dataset with the chart properties.
+ */
+  export interface IDataSet {
+    name: string,
+    label: string,
+    lineTension: 0,
+    bezierCurve: boolean;
+    fill: boolean,
+    borderColor: string,
+    data: IData[],
+    columnLabel:string
+  }
+
+/**
+ * Structure of chartjs dataset which is sent to the chart.
+ */
+  export interface IDataSetsObject  {
+    datasets: IDataSet[]
+  }
+
+/**
+ * Interface used by chart for sorting on time-stamp
+ */
+  export interface ITimeStamp {
+    "time-stamp": string;
+  }
+  
\ No newline at end of file
index f4afa64..b7277f7 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * Represents connected network elements.
  */
-export type ConnectedNetworkElements = {
-    mountId: string,
+
+export type ConnectedNetworkElementIds = {
+    mountId: string;
   }
index 2dc183e..43e74eb 100644 (file)
@@ -14,7 +14,6 @@ export type CrossPolarDiscriminationDataType = {
   "xpd-max": string;
 };
 
-
 export type CrossPolarDiscriminationResult = { "performance-data": CrossPolarDiscriminationDataType };
 
 export type CrossPolarDiscrimination = CrossPolarDiscriminationDataType & { _id: string };
\ No newline at end of file
index 6972998..3c9b5cb 100644 (file)
@@ -14,7 +14,6 @@ export type PerformanceDataType = {
   "unavailability": string;
 };
 
-
 export type PerformanceResult = { "performance-data": PerformanceDataType };
 
 export type Performance = PerformanceDataType & { _id: string };
\ No newline at end of file
index 9f51c8f..57ea48c 100644 (file)
@@ -14,7 +14,6 @@ export type ReceiveLevelDataType = {
   "rx-level-max": string;
 };
 
-
 export type ReceiveLevelResult = { "performance-data": ReceiveLevelDataType };
 
-export type ReceiveLevel = ReceiveLevelDataType & { _id: string };
\ No newline at end of file
+export type ReceiveLevel = ReceiveLevelDataType & { _id: string };
index 73934bd..51d43b4 100644 (file)
@@ -14,7 +14,6 @@ export type SignalToInterferenceDataType = {
   "snir-max": string;
 };
 
-
 export type SignalToInterferenceResult = { "performance-data": SignalToInterferenceDataType };
 
-export type SignalToInterference = SignalToInterferenceDataType & { _id: string };
\ No newline at end of file
+export type SignalToInterference = SignalToInterferenceDataType & { _id: string };
index e5be6e3..3179d7b 100644 (file)
@@ -14,7 +14,6 @@ export type TemperatureDataType = {
   "rf-temp-max": string;
 };
 
-
 export type TemperatureResult = { "performance-data": TemperatureDataType };
 
-export type Temperature = TemperatureDataType & { _id: string };
\ No newline at end of file
+export type Temperature = TemperatureDataType & { _id: string };
index 948baff..af6f989 100644 (file)
@@ -14,7 +14,6 @@ export type TransmissionPowerDataType = {
   "tx-level-max": string;
 };
 
-
 export type TransmissionPowerResult = { "performance-data": TransmissionPowerDataType };
 
-export type TransmissionPower = TransmissionPowerDataType & { _id: string };
\ No newline at end of file
+export type TransmissionPower = TransmissionPowerDataType & { _id: string };
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
new file mode 100644 (file)
index 0000000..d0b8346
--- /dev/null
@@ -0,0 +1,46 @@
+import { requestRest } from '../../../../framework/src/services/restService';
+import { Result } from '../../../../framework/src/models/elasticSearch';
+
+import { DistinctLtp, LtpIds } from '../models/availableLtps';
+
+/** 
+ * Represents a web api accessor service for Network elements actions.
+ */
+class PerformanceService {
+
+  /**
+   * Get distinct ltps based on the selected network element and time period from the historicalperformance15min database table.
+   */
+  public async getDistinctLtpsFromDatabase(networkElement: string, selectedTimePeriod: string): Promise<LtpIds[] | null> {
+    let path;
+    const query = {
+      "size": 0,
+      "query": {
+        "match": {
+          "node-name": networkElement
+        }
+      },
+      "aggs": {
+        "uuid-interface": {
+          "terms": {
+            "field": "uuid-interface"
+          }
+        }
+      }
+    };
+
+    if (selectedTimePeriod === "15min") {
+      path = 'database/sdnperformance/historicalperformance15min/_search';
+    } else {
+      path = 'database/sdnperformance/historicalperformance24h/_search';
+    }
+
+    const result = await requestRest<Result<DistinctLtp>>(path, { method: "POST", body: JSON.stringify(query) });
+    return result && result.aggregations && result.aggregations["uuid-interface"].buckets.map(ne => ({
+      key: ne.key
+    })) || null;
+  }
+}
+
+export const PerformanceHistoryService = new PerformanceService();
+export default PerformanceHistoryService;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.tsx
deleted file mode 100644 (file)
index a1cdcff..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-import { requestRest } from '../../../../framework/src/services/restService';
-import { Result } from '../../../../framework/src/models/elasticSearch';
-
-import { ConnectedNetworkElements } from '../models/connectedNetworkElements';
-import { DistinctLtp, Ltp } from '../models/availableLtps';
-import { Topology, TopologyNode } from '../models/topologyNetConf';
-
-/** 
- * Represents a web api accessor service for Network elements actions.
- */
-class PerformanceService {
-
-  private static networkElementTopology = (mountPoint: TopologyNode) => {
-    const mountId = mountPoint["node-id"];
-    return {
-      mountId: mountId,
-    }
-  }
-
-  /**
-   * Get all connected network elements from restconf.
-   */
-  public async getConnectedNetworkElementsList(): Promise<ConnectedNetworkElements[] | null> {
-    const path = "restconf/operational/network-topology:network-topology/topology/topology-netconf";
-    const topologyRequestPomise = requestRest<{ topology: Topology[] | null }>(path, { method: "GET" }, true);
-    const [netconfResponse] = await Promise.all([topologyRequestPomise]);
-    const topologyNetconf = netconfResponse && netconfResponse.topology && netconfResponse.topology.find(topology => topology["topology-id"] === "topology-netconf");
-    let mountPoints = topologyNetconf && topologyNetconf.node && topologyNetconf.node.filter(
-      mountPoint => mountPoint["netconf-node-topology:connection-status"] == "connected").map(mountedElement => {
-        return PerformanceService.networkElementTopology(mountedElement);
-      });
-    return mountPoints || [];
-  }
-
-  /**
-   * Get distinct ltps based on the selected network element and time period from the historicalperformance15min database table.
-   */
-  public async getDistinctLtpsFrom15minDatabase(networkElement: string): Promise<Ltp[] | null> {
-    const path = 'database/sdnperformance/historicalperformance15min/_search';
-    const query = {
-      "size": 0,
-      "query": {
-        "match": {
-          "node-name": networkElement
-        }
-      },
-      "aggs": {
-        "uuid-interface": {
-          "terms": {
-            "field": "uuid-interface"
-          }
-        }
-      }
-    };
-    const result = await requestRest<Result<DistinctLtp>>(path, { method: "POST", body: JSON.stringify(query) });
-    if(result && result.aggregations) {
-    }
-    return result && result.aggregations && result.aggregations["uuid-interface"].buckets.map(ne=>({
-      key:ne.key
-    }))|| null;
-  }
-
-  /**
-   * Get distinct ltps based on the selected network element and time period from the historicalperformance24h database table.
-   */
-  public async getDistinctLtpsFrom24hoursDatabase(networkElement: string): Promise<Ltp[] | null> {
-    const path = 'database/sdnperformance/historicalperformance24h/_search';
-    const query = {
-      "size": 0,
-      "query": {
-        "match": {
-          "node-name": networkElement
-        }
-      },
-      "aggs": {
-        "uuid-interface": {
-          "terms": {
-            "field": "uuid-interface"
-          }
-        }
-      }
-    };
-    const result = await requestRest<Result<DistinctLtp>>(path, { method: "POST", body: JSON.stringify(query) });
-    if(result && result.aggregations) {
-    }
-    return result && result.aggregations && result.aggregations["uuid-interface"].buckets.map(ne=>({
-      key:ne.key
-    }))|| null;
-  }
-}
-
-export const PerformanceHistoryService = new PerformanceService();
-export default PerformanceHistoryService;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
new file mode 100644 (file)
index 0000000..5d583e8
--- /dev/null
@@ -0,0 +1,51 @@
+import * as React from 'react';
+import { IDataSetsObject } from '../models/chartTypes';
+import { Line } from 'react-chartjs-2';
+import * as moment from 'moment';
+import { ITimeStamp } from 'models/chartTypes';
+
+export const lineChart = (chartPagedData: IDataSetsObject) => {
+  return (
+    <Line ref="chart" data={chartPagedData} options={{
+      scales: {
+        xAxes: [{
+          type: 'time',
+          time: {
+            displayFormats: {
+              'second': 'DD MMM YYYY HH:mm:ss',
+              'minute': 'DD MMM YYYY HH:mm:ss',
+              'hour': 'DD MMM YYYY HH:mm:ss',
+              'year': 'DD MMM YYYY HH:mm:ss',
+            },
+            parser: function (date: string) {
+              let offsetValue = new Date().getTimezoneOffset();
+              var utcDate = moment(date, 'YYYY-MM-DDTHH:mm:ss').utcOffset(offsetValue).utc(false);
+              return utcDate;
+            }
+          },
+          display: true,
+          scaleLabel: {
+            display: true,
+            labelString: 'Timestamp'
+          }
+        }],
+        yAxes: [{
+          ticks: {
+            beginAtZero: true
+          },
+          scaleLabel: {
+            display: true,
+            labelString: 'Value'
+          }
+        }]
+      }
+    }} />
+  );
+}
+
+export const sortDataByTimeStamp = <T extends ITimeStamp>(_rows: T[]): T[] => {
+  return (_rows.sort((a, b) => {
+    const result = Date.parse(a["time-stamp"]) - Date.parse(b["time-stamp"]);
+    return isNaN(result) ? 0 : result;
+  }));
+}
\ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/tableUtils.ts
new file mode 100644 (file)
index 0000000..ad50e51
--- /dev/null
@@ -0,0 +1,5 @@
+import { ColumnType, ColumnModel } from '../../../../framework/src/components/material-table';
+
+export const addColumnLabels = <T>(name: string, title: string, disableFilter = true, disableSorting = true): ColumnModel<T> => {
+  return { property: name as keyof T, title: title, type: ColumnType.text, disableFilter: disableFilter, disableSorting: disableSorting };
+}
index 12027e4..0cadfff 100644 (file)
@@ -10,14 +10,15 @@ import { IApplicationStoreState } from '../../../../framework/src/store/applicat
 import { Panel } from '../../../../framework/src/components/material-ui';
 
 import { PanelId } from '../models/panelId';
-import { PerformanceData } from '../components/performanceData';
-import { ReceiveLevel } from '../components/receiveLevel';
-import { TransmissionPower } from '../components/transmissionPower';
-import { AdaptiveModulation } from '../components/adaptiveModulation';
-import { Temperature } from '../components/temperature';
-import { SignalToInterference } from '../components/signalToInterference';
-import { CrossPolarDiscrimination } from '../components/crossPolarDiscrimination';
+import PerformanceData from '../components/performanceData';
+import ReceiveLevel from '../components/receiveLevel';
+import TransmissionPower from '../components/transmissionPower';
+import AdaptiveModulation from '../components/adaptiveModulation';
+import Temperature from '../components/temperature';
+import SignalToInterference from '../components/signalToInterference';
+import CrossPolarDiscrimination from '../components/crossPolarDiscrimination';
 import { loadAllConnectedNetworkElementsAsync } from '../actions/connectedNetworkElementsActions';
+import { loadAllMountedNetworkElementsAsync } from '../../../connectApp/src/actions/mountedNetworkElementsActions';
 import { loadDistinctLtpsbyNetworkElementAsync } from '../actions/ltpAction';
 import { SetPanelAction } from '../actions/panelChangeActions';
 import { createPerformanceData15minPreActions, performanceData15minReloadAction } from '../handlers/performanceData15minHandler';
@@ -35,6 +36,7 @@ import { createSignalToInterference24hoursPreActions, signalToInterference24hour
 import { createCrossPolarDiscrimination15minPreActions, crossPolarDiscrimination15minReloadAction } from '../handlers/crossPolarDiscrimination15minHandler';
 import { createCrossPolarDiscrimination24hoursPreActions, crossPolarDiscrimination24hoursReloadAction } from '../handlers/crossPolarDiscrimination24hoursHandler';
 
+
 const PerformanceHistoryComponentStyles = (theme: Theme) => createStyles({
   root: {
     display: "flex",
@@ -61,7 +63,7 @@ const PerformanceHistoryComponentStyles = (theme: Theme) => createStyles({
 const mapProps = (state: IApplicationStoreState) => ({
   activePanel: state.performanceHistory.currentOpenPanel,
   availableLtps: state.performanceHistory.ltps.distinctLtps,
-  networkElements: state.performanceHistory.networkElements.connectedNetworkElements
+  networkElements: state.performanceHistory.networkElements.connectedNetworkElementIds
 });
 
 const mapDispatcher = (dispatcher: IDispatcher) => ({
@@ -93,8 +95,11 @@ const mapDispatcher = (dispatcher: IDispatcher) => ({
   signalToInterference24hoursPreActions: createSignalToInterference24hoursPreActions(dispatcher.dispatch),
   crossPolarDiscrimination15minPreActions: createCrossPolarDiscrimination15minPreActions(dispatcher.dispatch),
   crossPolarDiscrimination24hoursPreActions: createCrossPolarDiscrimination24hoursPreActions(dispatcher.dispatch),
-  getConnectedNetworkElements: () => dispatcher.dispatch(loadAllConnectedNetworkElementsAsync),
-  getDistinctLtps: (selectedNetworkElement: string, selectedTimePeriod: string, selectedLtp: string, selectFirstLtp?: Function, resetLTP?: Function) => dispatcher.dispatch(loadDistinctLtpsbyNetworkElementAsync(selectedNetworkElement, selectedTimePeriod, selectedLtp, selectFirstLtp, resetLTP)),
+  getConnectedNetworkElementsIds: async() => {
+    await dispatcher.dispatch(loadAllMountedNetworkElementsAsync)
+    dispatcher.dispatch(loadAllConnectedNetworkElementsAsync);
+  },
+  getDistinctLtpsIds: (selectedNetworkElement: string, selectedTimePeriod: string, selectedLtp: string, selectFirstLtp?: Function, resetLTP?: Function) => dispatcher.dispatch(loadDistinctLtpsbyNetworkElementAsync(selectedNetworkElement, selectedTimePeriod, selectedLtp, selectFirstLtp, resetLTP)),
   setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId))
 });
 
@@ -135,58 +140,56 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
       this.props.setCurrentPanel(nextActivePanel);
       switch (nextActivePanel) {
         case "PerformanceData":
-          if (this.state.selectedTimePeriod == "15min") {
+          if (this.state.selectedTimePeriod === "15min") {
             this.props.reloadPerformanceData15min();
           } else {
-
             this.props.reloadPerformanceData24hours();
           }
           break;
         case "ReceiveLevel":
-          if (this.state.selectedTimePeriod == "15min") {
+          if (this.state.selectedTimePeriod === "15min") {
             this.props.reloadReceiveLevel15min();
           } else {
             this.props.reloadReceiveLevel24hours();
           }
           break;
         case "TransmissionPower":
-          if (this.state.selectedTimePeriod == "15min") {
+          if (this.state.selectedTimePeriod === "15min") {
             this.props.reloadTransmissionPower15min();
           } else {
             this.props.reloadTransmissionPower24hours();
           }
           break;
         case "AdaptiveModulation":
-          if (this.state.selectedTimePeriod == "15min") {
+          if (this.state.selectedTimePeriod === "15min") {
             this.props.reloadAdaptiveModulation15min();
           } else {
             this.props.reloadAdaptiveModulation24hours();
           }
           break;
         case "Temperature":
-          if (this.state.selectedTimePeriod == "15min") {
+          if (this.state.selectedTimePeriod === "15min") {
             this.props.reloadTemperature15min();
           } else {
             this.props.reloadTemperature24hours();
           }
           break;
         case "SINR":
-          if (this.state.selectedTimePeriod == "15min") {
+          if (this.state.selectedTimePeriod === "15min") {
             this.props.reloadSignalToInterference15min();
           } else {
             this.props.reloadSignalToInterference24hours();
           }
           break;
         case "CPD":
-          if (this.state.selectedTimePeriod == "15min") {
+          if (this.state.selectedTimePeriod === "15min") {
             this.props.reloadCrossPolarDiscrimination15min();
           } else {
             this.props.reloadCrossPolarDiscrimination24hours();
           }
           break;
-        case null:
-          break;
         default:
+          // do nothing if all panels are closed
           break;
       }
     }
@@ -255,7 +258,7 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
   };
 
   public componentDidMount() {
-    this.props.getConnectedNetworkElements();
+    this.props.getConnectedNetworkElementsIds();
   }
 
   /**
@@ -277,7 +280,7 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
       "node-name": networkElement,
       "uuid-interface": ltp
     };
-    if (timePeriod == "15min") {
+    if (timePeriod === "15min") {
       this.props.performanceData15minPreActions.onPreFilterChanged(preFilter);
       this.props.receiveLevel15minPreActions.onPreFilterChanged(preFilter);
       this.props.transmissionPower15minPreActions.onPreFilterChanged(preFilter);
@@ -285,7 +288,7 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
       this.props.temperature15minPreActions.onPreFilterChanged(preFilter);
       this.props.signalToInterference15minPreActions.onPreFilterChanged(preFilter);
       this.props.crossPolarDiscrimination15minPreActions.onPreFilterChanged(preFilter);
-    } else if (timePeriod == "24hours") {
+    } else if (timePeriod === "24hours") {
       this.props.performanceData24hoursPreActions.onPreFilterChanged(preFilter);
       this.props.receiveLevel24hoursPreActions.onPreFilterChanged(preFilter);
       this.props.transmissionPower24hoursPreActions.onPreFilterChanged(preFilter);
@@ -313,7 +316,7 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
       selectedNetworkElement: event.target.value,
       selectedLtp: "-1"
     });
-    this.props.getDistinctLtps(event.target.value, this.state.selectedTimePeriod, "-1", this.selectFirstLtp);
+    this.props.getDistinctLtpsIds(event.target.value, this.state.selectedTimePeriod, "-1", this.selectFirstLtp);
   }
 
   /**
@@ -335,10 +338,10 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
     this.setState({
       selectedTimePeriod: event.target.value,
     });
-    if (event.target.value == "15min") {
-      this.props.getDistinctLtps(this.state.selectedNetworkElement, event.target.value, this.state.selectedLtp, undefined, this.resetLtpDropdown);
-    } else if (event.target.value == "24hours") {
-      this.props.getDistinctLtps(this.state.selectedNetworkElement, event.target.value, this.state.selectedLtp, undefined, this.resetLtpDropdown);
+    if (event.target.value === "15min") {
+      this.props.getDistinctLtpsIds(this.state.selectedNetworkElement, event.target.value, this.state.selectedLtp, undefined, this.resetLtpDropdown);
+    } else if (event.target.value === "24hours") {
+      this.props.getDistinctLtpsIds(this.state.selectedNetworkElement, event.target.value, this.state.selectedLtp, undefined, this.resetLtpDropdown);
     }
     this.preFilterChangeAndReload(this.state.selectedNetworkElement, event.target.value, this.state.selectedLtp);
   }
@@ -359,5 +362,5 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
   }
 }
 
-export const PerformanceHistoryApplication = withStyles(PerformanceHistoryComponentStyles)(connect(mapProps, mapDispatcher)(PerformanceHistoryComponent));
+const PerformanceHistoryApplication = withStyles(PerformanceHistoryComponentStyles)(connect(mapProps, mapDispatcher)(PerformanceHistoryComponent));
 export default PerformanceHistoryApplication;
index 1ffdd39..f1588ce 100644 (file)
@@ -16,7 +16,7 @@
        <properties>
                <buildtime>${maven.build.timestamp}</buildtime>
                <distversion>ONAP Dublin (Flourine-SR2)</distversion>
-               <buildno>9.ac4a3af(19/06/06)</buildno>
+               <buildno>10.2befc1b(19/06/07)</buildno>
                <odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version>
        </properties>
        <licenses>
index 2abe821..a159cb6 100644 (file)
@@ -3,6 +3,8 @@ import { UpdateAuthentication } from '../actions/authentication';
 
 import { User } from '../models/authentication';
 
+import { onLogin, onLogout } from '../services/applicationApi';
+
 export interface IAuthenticationState {
   user?: User;
 }
@@ -19,8 +21,10 @@ export const authenticationStateHandler: IActionHandler<IAuthenticationState> =
     const user = action.bearerToken && new User(action.bearerToken) || undefined;
     if (user) {
       localStorage.setItem("userToken", user.toString());
+      onLogin();
     } else {
       localStorage.removeItem("userToken");
+      onLogout();
     }
 
     state = {
index bddfb24..b097b23 100644 (file)
@@ -1,10 +1,21 @@
+import { Event } from '../common/event';
 import { ApplicationStore } from '../store/applicationStore';
 
-
 let resolveApplicationStoreInitialized: (store: ApplicationStore) => void;
 let applicationStore: ApplicationStore | null = null;
 const applicationStoreInitialized: Promise<ApplicationStore> = new Promise((resolve) => resolveApplicationStoreInitialized = resolve);
 
+const loginEvent = new Event();
+const logoutEvent = new Event();
+
+export const onLogin = () => {
+  loginEvent.invoke();
+}
+
+export const onLogout = () => {
+  logoutEvent.invoke();
+}
+
 export const setApplicationStore = (store: ApplicationStore) => {
   if (!applicationStore && store) {
     applicationStore = store;
@@ -19,6 +30,14 @@ export const applicationApi = {
 
   get applicationStoreInitialized(): Promise<ApplicationStore> {
     return applicationStoreInitialized;
+  },
+
+  get loginEvent() {
+    return loginEvent;
+  },
+
+  get logoutEvent() {
+    return logoutEvent;
   }
 };
 
index c2ef0de..8c3e511 100644 (file)
@@ -2605,6 +2605,29 @@ chardet@^0.7.0:
   resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
   integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==
 
+chart.js@2.8.0:
+  version "2.8.0"
+  resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.8.0.tgz#b703b10d0f4ec5079eaefdcd6ca32dc8f826e0e9"
+  integrity sha512-Di3wUL4BFvqI5FB5K26aQ+hvWh8wnP9A3DWGvXHVkO13D3DSnaSsdZx29cXlEsYKVkn1E2az+ZYFS4t0zi8x0w==
+  dependencies:
+    chartjs-color "^2.1.0"
+    moment "^2.10.2"
+
+chartjs-color-string@^0.6.0:
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71"
+  integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==
+  dependencies:
+    color-name "^1.0.0"
+
+chartjs-color@^2.1.0:
+  version "2.3.0"
+  resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.3.0.tgz#0e7e1e8dba37eae8415fd3db38bf572007dd958f"
+  integrity sha512-hEvVheqczsoHD+fZ+tfPUE+1+RbV6b+eksp2LwAhwRTVXEjCSEavvk+Hg3H6SZfGlPh/UfmWKGIvZbtobOEm3g==
+  dependencies:
+    chartjs-color-string "^0.6.0"
+    color-convert "^0.5.3"
+
 chokidar@^2.0.0, chokidar@^2.0.2:
   version "2.0.4"
   resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.0.4.tgz#356ff4e2b0e8e43e322d18a372460bbcf3accd26"
@@ -2734,6 +2757,11 @@ collection-visit@^1.0.0:
     map-visit "^1.0.0"
     object-visit "^1.0.0"
 
+color-convert@^0.5.3:
+  version "0.5.3"
+  resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-0.5.3.tgz#bdb6c69ce660fadffe0b0007cc447e1b9f7282bd"
+  integrity sha1-vbbGnOZg+t/+CwAHzER+G59ygr0=
+
 color-convert@^1.9.0:
   version "1.9.3"
   resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@@ -2744,6 +2772,11 @@ color-name@1.1.3:
   version "1.1.3"
   resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
 
+color-name@^1.0.0:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+  integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
 colors@1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b"
@@ -3676,9 +3709,9 @@ es-to-primitive@^1.1.1:
     is-symbol "^1.0.1"
 
 es6-promise@^4.0.3:
-  version "4.2.6"
-  resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.6.tgz#b685edd8258886365ea62b57d30de28fadcd974f"
-  integrity sha512-aRVgGdnmW2OiySVPUC9e6m+plolMAJKjZnQlCwNSuK5yQ0JN61DZSO1X1Ufd1foqWRAlig0rhduTCHe7sVtK5Q==
+  version "4.2.8"
+  resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a"
+  integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==
 
 es6-promisify@^5.0.0:
   version "5.0.0"
@@ -6679,6 +6712,11 @@ modify-values@^1.0.0:
   resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022"
   integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==
 
+moment@^2.10.2:
+  version "2.24.0"
+  resolved "https://registry.yarnpkg.com/moment/-/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
+  integrity sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==
+
 move-concurrently@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92"
@@ -6694,7 +6732,12 @@ ms@2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
 
-ms@^2.0.0, ms@^2.1.1:
+ms@^2.0.0:
+  version "2.1.2"
+  resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+  integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+ms@^2.1.1:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a"
 
@@ -7726,6 +7769,15 @@ prop-types@15.6.2, prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.1,
     loose-envify "^1.3.1"
     object-assign "^4.1.1"
 
+prop-types@^15.5.8:
+  version "15.7.2"
+  resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
+  integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
+  dependencies:
+    loose-envify "^1.4.0"
+    object-assign "^4.1.1"
+    react-is "^16.8.1"
+
 proto-list@~1.2.1:
   version "1.2.4"
   resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
@@ -7890,6 +7942,14 @@ rc@^1.2.7:
     minimist "^1.2.0"
     strip-json-comments "~2.0.1"
 
+react-chartjs-2@2.7.6:
+  version "2.7.6"
+  resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-2.7.6.tgz#b8cd29bed00bf55b9e8172b06466b4ecf2b86bfb"
+  integrity sha512-xDr0jhgt/o26atftXxTVsepz+QYZI2GNKBYpxtLvYgwffLUm18a9n562reUJAHvuwKsy2v+qMlK5HyjFtSW0mg==
+  dependencies:
+    lodash "^4.17.4"
+    prop-types "^15.5.8"
+
 react-dom@16.5.2:
   version "16.5.2"
   resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.5.2.tgz#b69ee47aa20bab5327b2b9d7c1fe2a30f2cfa9d7"
@@ -7912,6 +7972,11 @@ react-is@^16.3.2, react-is@^16.6.3:
   resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.7.0.tgz#c1bd21c64f1f1364c6f70695ec02d69392f41bfa"
   integrity sha512-Z0VRQdF4NPDoI0tsXVMLkJLiwEBa+RP66g0xDHxgxysxSoCUccSten4RTF/UFvZF1dZvZ9Zu1sx+MDXwcOR34g==
 
+react-is@^16.8.1:
+  version "16.8.6"
+  resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16"
+  integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA==
+
 react-lifecycles-compat@^3.0.2, react-lifecycles-compat@^3.0.4:
   version "3.0.4"
   resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz#4f1a273afdfc8f3488a8c516bfda78f872352362"