aboutsummaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/apps
diff options
context:
space:
mode:
Diffstat (limited to 'sdnr/wt/odlux/apps')
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx15
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx2
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx79
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx4
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts9
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx4
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts6
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts13
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx16
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx25
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts60
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts11
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts37
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx44
-rw-r--r--sdnr/wt/odlux/apps/inventoryApp/webpack.config.js10
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx24
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx2
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx2
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts16
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts24
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx22
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx50
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx20
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx22
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx20
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx23
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx20
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx22
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx70
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx22
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts34
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts48
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts2
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx21
34 files changed, 632 insertions, 167 deletions
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
index 9c92ceb6b..06de39b9d 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx
@@ -65,7 +65,7 @@ const styles = (theme: Theme) => createStyles({
},
outer: {
"flex": "1",
- "heigh": "100%",
+ "height": "100%",
"display": "flex",
"alignItems": "center",
"justifyContent": "center",
@@ -73,6 +73,11 @@ const styles = (theme: Theme) => createStyles({
inner: {
},
+ container: {
+ "height": "100%",
+ "display": "flex",
+ "flexDirection": "column",
+ },
"icon": {
"marginRight": theme.spacing(0.5),
"width": 20,
@@ -440,7 +445,7 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
const { classes } = this.props;
return (
- <SelectElementTable idProperty={listKeyProperty} rows={listData} customActionButtons={[addNewElementAction]} columns={
+ <SelectElementTable stickyHeader idProperty={listKeyProperty} rows={listData} customActionButtons={[addNewElementAction]} columns={
Object.keys(listElements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
const elm = listElements[cur];
if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) {
@@ -571,8 +576,8 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
}
return (
- <div>
- <SelectElementTable idProperty={listKeyProperty} rows={listData} columns={
+ <div className={this.props.classes.container}>
+ <SelectElementTable stickyHeader idProperty={listKeyProperty} rows={listData} columns={
Object.keys(listSpecification.elements).reduce<ColumnModel<{ [key: string]: any }>[]>((acc, cur) => {
const elm = listSpecification.elements[cur];
if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) {
@@ -594,7 +599,7 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp
const { viewData, editMode, isNew } = this.state;
return (
- <div>
+ <div className={this.props.classes.container}>
{this.renderBreadCrumps()}
{displayAsList && viewData instanceof Array
? this.renderUIViewList(viewSpecification, keyProperty!, viewData)
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
index 8155becbb..c153ed5a1 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
@@ -47,7 +47,7 @@ class NetworkElementSelectorComponent extends React.Component<NetworkElementSele
render() {
return (
- <ConnectedElementTable onHandleClick={(e, row) => { this.props.history.push(`${this.props.match.path}/${row.nodeId}`) }} columns={[
+ <ConnectedElementTable stickyHeader onHandleClick={(e, row) => { this.props.history.push(`${this.props.match.path}/${row.nodeId}`) }} columns={[
{ property: "nodeId", title: "Name", type: ColumnType.text },
{ property: "isRequired", title: "Required ?", type: ColumnType.boolean },
{ property: "host", title: "Host", type: ColumnType.text },
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
index ce7f48cc9..e3b640120 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx
@@ -24,7 +24,7 @@ import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';
-import { FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
+import { FormControl, InputLabel, Select, MenuItem, Typography } from '@material-ui/core';
import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect';
@@ -35,7 +35,7 @@ import {
} from '../actions/networkElementsActions';
import { unmountNetworkElementAsyncActionCreator, mountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions';
-import { NetworkElementConnection, UpdateNetworkElement } from '../models/networkElementConnection';
+import { NetworkElementConnection, UpdateNetworkElement, propertyOf } from '../models/networkElementConnection';
import { removeWebUriAction } from '../actions/commonNetworkElementsActions';
export enum EditNetworkElementDialogMode {
@@ -47,6 +47,8 @@ export enum EditNetworkElementDialogMode {
UnmountNetworkElement = "unmountNetworkElement",
}
+
+
const mapDispatch = (dispatcher: IDispatcher) => ({
addNewNetworkElement: async (element: NetworkElementConnection) => {
await dispatcher.dispatch(addNewNetworkElementAsyncActionCreator(element));
@@ -57,8 +59,21 @@ const mapDispatch = (dispatcher: IDispatcher) => ({
dispatcher.dispatch(unmountNetworkElementAsyncActionCreator(element && element.nodeId));
},
editNetworkElement: async (element: UpdateNetworkElement, mountElement: NetworkElementConnection) => {
- await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
- await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement));
+
+ const values = Object.keys(element);
+
+ //make sure properties are there in case they get renamed
+ const idProperty = propertyOf<UpdateNetworkElement>("id");
+ const isRequiredProperty = propertyOf<UpdateNetworkElement>("isRequired");
+
+ if (values.length === 2 && values.includes(idProperty as string) && values.includes(isRequiredProperty as string)) {
+ // do not mount network element, if only isRequired is changed
+ await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
+
+ } else {
+ await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element));
+ await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement));
+ }
},
removeNetworkElement: async (element: UpdateNetworkElement) => {
await dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element));
@@ -140,7 +155,7 @@ type EditNetworkElementDialogComponentProps = Connect<undefined, typeof mapDispa
onClose: () => void;
};
-type EditNetworkElementDialogComponentState = NetworkElementConnection;
+type EditNetworkElementDialogComponentState = NetworkElementConnection & { isNameValid: boolean, isHostSet: boolean };
class EditNetworkElementDialogComponent extends React.Component<EditNetworkElementDialogComponentProps, EditNetworkElementDialogComponentState> {
constructor(props: EditNetworkElementDialogComponentProps) {
@@ -151,6 +166,8 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
isRequired: false,
host: this.props.initialNetworkElement.host,
port: this.props.initialNetworkElement.port,
+ isNameValid: true,
+ isHostSet: true
};
}
@@ -164,7 +181,9 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
{setting.dialogDescription}
</DialogContentText>
<TextField disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" id="name" label="Name" aria-label="name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
+ {!this.state.isNameValid && <Typography variant="body1" color="error">Name cannot be empty.</Typography>}
<TextField disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="ipaddress" label="IP address" aria-label="ip adress" type="text" fullWidth value={this.state.host} onChange={(event) => { this.setState({ host: event.target.value }); }} />
+ {!this.state.isHostSet && <Typography variant="body1" color="error">IP Adress cannot be empty.</Typography>}
<TextField disabled={!setting.enableMountIdEditor} spellCheck={false} margin="dense" id="netconfport" label="NetConf port" aria-label="netconf port" type="number" fullWidth value={this.state.port.toString()} onChange={(event) => { this.setState({ port: +event.target.value }); }} />
{setting.enableUsernameEditor && <TextField disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" id="username" label="Username" aria-label="username" type="text" fullWidth value={this.state.username} onChange={(event) => { this.setState({ username: event.target.value }); }} /> || null}
{setting.enableUsernameEditor && <TextField disabled={!setting.enableUsernameEditor} spellCheck={false} margin="dense" id="password" label="Password" aria-label="password" type="password" fullWidth value={this.state.password} onChange={(event) => { this.setState({ password: event.target.value }); }} /> || null}
@@ -180,15 +199,18 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
</DialogContent>
<DialogActions>
<Button aria-label="dialog-confirm-button" onClick={(event) => {
- this.onApply({
- isRequired: this.state.isRequired,
- id: this.state.nodeId,
- nodeId: this.state.nodeId,
- host: this.state.host,
- port: this.state.port,
- username: this.state.username,
- password: this.state.password,
- });
+
+ if (this.areRequieredFieldsValid()) {
+ this.onApply({
+ isRequired: this.state.isRequired,
+ id: this.state.nodeId,
+ nodeId: this.state.nodeId,
+ host: this.state.host,
+ port: this.state.port,
+ username: this.state.username,
+ password: this.state.password,
+ });
+ }
event.preventDefault();
event.stopPropagation();
}} > {setting.applyButtonText} </Button>
@@ -230,10 +252,39 @@ class EditNetworkElementDialogComponent extends React.Component<EditNetworkEleme
element && this.props.removeNetworkElement(updateElement);
break;
}
+
+ this.setState({ password: '', username: '' });
+ this.resetRequieredFields();
};
private onCancel = () => {
this.props.onClose && this.props.onClose();
+ this.setState({ password: '', username: '' });
+ this.resetRequieredFields();
+ }
+
+ private resetRequieredFields() {
+ this.setState({ isNameValid: true, isHostSet: true });
+ }
+
+ private areRequieredFieldsValid() {
+ let areFieldsValid = true;
+
+ if (this.state.nodeId == undefined || this.state.nodeId.trim().length === 0) {
+ this.setState({ isNameValid: false });
+ areFieldsValid = false;
+ } else {
+ this.setState({ isNameValid: true });
+ }
+
+ if (this.state.host == undefined || this.state.host.trim().length === 0) {
+ this.setState({ isHostSet: false });
+ areFieldsValid = false;
+ } else {
+ this.setState({ isHostSet: true });
+ }
+
+ return areFieldsValid;
}
static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection }): EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection } {
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
index 45003e741..d50a81ed5 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
@@ -110,9 +110,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
<Divider />,
<MenuItem aria-label={"info-button"} onClick={event => this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected"} ><Info /><Typography>Info</Typography></MenuItem>,
<MenuItem aria-label={"edit-button"} onClick={event => this.onOpenEditNetworkElementDialog(event, rowData)}><EditIcon /><Typography>Edit</Typography></MenuItem>,
- !rowData.isRequired
- ? <MenuItem aria-label={"add-button"} onClick={event => this.onOpenAddNetworkElementDialog(event, rowData)} ><AddIcon /><Typography>Add</Typography></MenuItem>
- : <MenuItem aria-label={"remove-button"} onClick={event => this.onOpenRemoveNetworkElementDialog(event, rowData)} ><RemoveIcon /><Typography>Remove</Typography></MenuItem>,
+ <MenuItem aria-label={"remove-button"} onClick={event => this.onOpenRemoveNetworkElementDialog(event, rowData)} ><RemoveIcon /><Typography>Remove</Typography></MenuItem>,
<Divider />,
<MenuItem aria-label={"inventory-button"} onClick={event => this.props.navigateToApplication("inventory", rowData.nodeId)}><Typography>Inventory</Typography></MenuItem>,
<Divider />,
diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
index f58dc58ab..b3586d693 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
+++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts
@@ -51,4 +51,11 @@ export type UpdateNetworkElement = {
export type ConnectionStatus = {
status: string
-} \ No newline at end of file
+}
+
+/**
+ * Checks if a object has a given propertyname, if yes, the name is returned as string.
+ * @throws at compile time if property is not available
+ * @param name propertyname
+ */
+export const propertyOf = <TObj>(name: keyof TObj) => name; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx b/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx
index 535de1f1d..5993bb5c4 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx
+++ b/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx
@@ -24,7 +24,7 @@ import { EventLogType } from '../models/eventLogType';
import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
import { createEventLogProperties, createEventLogActions } from "../handlers/eventLogHandler";
-const EventLogTable = MaterialTable as MaterialTableCtorType<EventLogType & {_id: string}>;
+const EventLogTable = MaterialTable as MaterialTableCtorType<EventLogType & { _id: string }>;
const mapProps = (state: IApplicationStoreState) => ({
eventLogProperties: createEventLogProperties(state),
@@ -37,7 +37,7 @@ const mapDispatch = (dispatcher: IDispatcher) => ({
class EventLogComponent extends React.Component<Connect<typeof mapProps, typeof mapDispatch>> {
render() {
- return <EventLogTable title="Event Log" idProperty="_id" columns={[
+ return <EventLogTable stickyHeader title="Event Log" idProperty="_id" columns={[
{ property: "nodeId", title: "Node Name" },
{ property: "counter", title: "Counter" },
{ property: "timestamp", title: "Timestamp" },
diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts
index 58da19d46..7cf02ac4f 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/panelChangeActions.ts
@@ -24,6 +24,12 @@ export class SetPanelAction extends Action {
}
}
+export class RememberCurrentPanelAction extends Action {
+ constructor(public panelId: PanelId) {
+ super();
+ }
+}
+
export const setPanelAction = (panelId: PanelId) => {
return new SetPanelAction(panelId);
}
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
index dddb4a247..a5cf928fc 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
@@ -26,21 +26,26 @@ import { IActionHandler } from '../../../../framework/src/flux/action';
import { IFaultNotifications, faultNotificationsHandler } from './notificationsHandler';
import { ICurrentProblemsState, currentProblemsActionHandler } from './currentProblemsHandler';
import { IAlarmLogEntriesState, alarmLogEntriesActionHandler } from './alarmLogEntriesHandler';
-import { SetPanelAction } from '../actions/panelChangeActions';
+import { SetPanelAction, RememberCurrentPanelAction } from '../actions/panelChangeActions';
import { IFaultStatus, faultStatusHandler } from './faultStatusHandler';
import { stuckAlarmHandler } from './clearStuckAlarmsHandler';
+import { PanelId } from 'models/panelId';
export interface IFaultAppStoreState {
currentProblems: ICurrentProblemsState;
faultNotifications: IFaultNotifications;
alarmLogEntries: IAlarmLogEntriesState;
- currentOpenPanel: string | null;
+ currentOpenPanel: ICurrentOpenPanelState;
faultStatus: IFaultStatus;
}
-const currentOpenPanelHandler: IActionHandler<string | null> = (state = null, action) => {
+type ICurrentOpenPanelState = { openPanel: string | null, savedPanel: PanelId | null };
+const panelInitState = { openPanel: null, savedPanel: null };
+const currentOpenPanelHandler: IActionHandler<ICurrentOpenPanelState> = (state = panelInitState, action) => {
if (action instanceof SetPanelAction) {
- state = action.panelId;
+ state = { ...state, openPanel: action.panelId };
+ } else if (action instanceof RememberCurrentPanelAction) {
+ state = { ...state, savedPanel: action.panelId };
}
return state;
}
diff --git a/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
index 02dde90f7..666667e40 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
@@ -40,6 +40,7 @@ import { AddFaultNotificationAction } from "./actions/notificationActions";
import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from "./handlers/currentProblemsHandler";
import { FaultStatus } from "./components/faultStatus";
import { refreshFaultStatusAsyncAction } from "./actions/statusActions";
+import { alarmLogEntriesReloadAction } from "./handlers/alarmLogEntriesHandler";
let currentMountId: string | undefined = undefined;
@@ -49,7 +50,7 @@ const mapProps = (state: IApplicationStoreState) => ({
const mapDisp = (dispatcher: IDispatcher) => ({
currentProblemsActions: createCurrentProblemsActions(dispatcher.dispatch, true),
- setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId))
+ setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)),
});
const FaultApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect<typeof mapProps, typeof mapDisp>) => {
@@ -73,9 +74,9 @@ const FaultApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteCom
const App = withRouter((props: RouteComponentProps) => (
<Switch>
- <Route path={ `${ props.match.path }/:mountId?` } component={ FaultApplicationRouteAdapter } />
- <Redirect to={ `${ props.match.path }` } />
- </Switch>
+ <Route path={`${props.match.path}/:mountId?`} component={FaultApplicationRouteAdapter} />
+ <Redirect to={`${props.match.path}`} />
+ </Switch>
));
export function register() {
@@ -93,6 +94,13 @@ export function register() {
const store = applicationApi && applicationApi.applicationStore;
if (fault && store) {
store.dispatch(new AddFaultNotificationAction(fault));
+
+ //reload fault data if tab is open
+ if (store.state.fault.currentOpenPanel.openPanel === "AlarmLog") {
+ store.dispatch(alarmLogEntriesReloadAction);
+ } else if (store.state.fault.currentOpenPanel.openPanel === "CurrentProblem") {
+ store.dispatch(currentProblemsReloadAction);
+ }
}
}));
diff --git a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
index cbcfd84d6..ed395d2e4 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
@@ -33,13 +33,14 @@ import { PanelId } from '../models/panelId';
import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from '../handlers/currentProblemsHandler';
import { createAlarmLogEntriesProperties, createAlarmLogEntriesActions, alarmLogEntriesReloadAction } from '../handlers/alarmLogEntriesHandler';
-import { setPanelAction } from '../actions/panelChangeActions';
+import { setPanelAction, RememberCurrentPanelAction } from '../actions/panelChangeActions';
import { Tooltip, IconButton, AppBar, Tabs, Tab } from '@material-ui/core';
import RefreshIcon from '@material-ui/icons/Refresh';
import ClearStuckAlarmsDialog, { ClearStuckAlarmsDialogMode } from '../components/clearStuckAlarmsDialog';
const mapProps = (state: IApplicationStoreState) => ({
- panelId: state.fault.currentOpenPanel,
+ panelId: state.fault.currentOpenPanel.openPanel,
+ savedPanel: state.fault.currentOpenPanel.savedPanel,
currentProblemsProperties: createCurrentProblemsProperties(state),
faultNotifications: state.fault.faultNotifications,
alarmLogEntriesProperties: createAlarmLogEntriesProperties(state)
@@ -52,7 +53,8 @@ const mapDisp = (dispatcher: IDispatcher) => ({
reloadAlarmLogEntries: () => dispatcher.dispatch(alarmLogEntriesReloadAction),
switchActivePanel: (panelId: PanelId) => {
dispatcher.dispatch(setPanelAction(panelId));
- }
+ },
+ rememberCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new RememberCurrentPanelAction(panelId))
});
type FaultApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp>;
@@ -146,7 +148,7 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen
{ property: "icon", title: "", type: ColumnType.custom, customControl: this.renderIcon },
{ property: "timeStamp", title: "Time Stamp" },
{ property: "nodeName", title: "Node Name" },
- { property: "counter", title: "Count", width: "100px" },
+ { property: "counter", title: "Count", width: "100px", type: ColumnType.numeric },
{ property: "objectId", title: "Object Id" },
{ property: "problem", title: "Alarm Type" },
{ property: "severity", title: "Severity", width: "140px" },
@@ -174,11 +176,22 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen
};
+ componentWillUnmount() {
+ if (this.props.panelId) {
+ this.props.rememberCurrentPanel(this.props.panelId as PanelId);
+ this.props.switchActivePanel(null);
+ }
+ }
+
public componentDidMount() {
- if (this.props.panelId === null) { //don't change tabs, if one is selected already
+ if (this.props.panelId === null && this.props.savedPanel === null) { //set default tab if none is set
this.onToggleTabs("CurrentProblem");
- }
+ } else // load saved tab if possible
+ if (this.props.panelId === null && this.props.savedPanel !== null) {
+ this.onToggleTabs(this.props.savedPanel);
+ this.props.rememberCurrentPanel(null);
+ }
this.props.alarmLogEntriesActions.onToggleFilter();
this.props.currentProblemsActions.onToggleFilter();
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts b/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts
new file mode 100644
index 000000000..692ea82c7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts
@@ -0,0 +1,60 @@
+import { InventoryTreeNode, InventoryType } from "models/inventory";
+import { convertPropertyNames, replaceHyphen } from "../../../../framework/src/utilities/yangHelper";
+
+// Tree mittels tree-level und parent UUID (incl)
+// einzelabfrage mit db-id
+const data = [
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.1.5", "part-type-id": "3FE25774AA01", "model-identifier": "VAUIAEYAAA", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/CORE-MAIN/a2.module#5", "type-name": "a2.module", "serial": "0003548168", "id": "robot_sim_2_equipment/a2.module-1.1.1.5", "parent-uuid": "CARD-1.1.1.0", "contained-holder": ["SUBRACK-1.15.0.0"], "date": "2005-11-09T00:00:00.0Z" },
+ { "manufacturer-identifier": "SAN", "version": "234", "uuid": "CARD-1.1.6.0", "part-type-id": "part-number-12", "model-identifier": "model-id-12", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module", "type-name": "p8.module", "serial": "serial-number-124", "id": "robot_sim_2_equipment/CARD-1.1.6.0", "parent-uuid": "SHELF-1.1.0.0", "contained-holder": ["PORT-1.1.6.5", "PORT-1.1.6.8", "PORT-1.1.6.7", "PORT-1.1.6.6"], "date": "2013-11-23T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.6.5", "part-type-id": "3EM23141AD01", "model-identifier": "CRPQABVFAA", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module/a2.module#5", "type-name": "a2.module", "serial": "310330008", "id": "robot_sim_2_equipment/a2.module-1.1.6.5", "parent-uuid": "CARD-1.1.6.0", "contained-holder": ["SUBRACK-1.65.0.0"], "date": "2013-04-13T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "2017", "uuid": "CARD-1.55.1.4", "part-type-id": "partNo2017-12", "model-identifier": "model-id-s3s", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "MWR#55Ch#1/RxDiv", "type-name": "RxDiv", "serial": "Serie2017-12", "id": "robot_sim_2_equipment/CARD-1.55.1.4", "parent-uuid": "IDU-1.55.0.0", "date": "2014-01-07T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.56.1.2", "part-type-id": "Partnumber", "model-identifier": "model-id", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "MWR#56Ch#1/a2.moduletraff", "type-name": "a2.module", "serial": "Serial1", "id": "robot_sim_2_equipment/a2.module-1.56.1.2", "parent-uuid": "ODU-1.56.0.0", "date": "2017-09-09T00:00:00.0Z" },
+ { "manufacturer-identifier": "SAN", "version": "123", "uuid": "CARD-1.1.1.0", "part-type-id": "part-number-2", "model-identifier": "model-id-2", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/CORE-MAIN", "type-name": "latest", "serial": "asdf-asdasd-asd", "id": "robot_sim_2_equipment/CARD-1.1.1.0", "parent-uuid": "SHELF-1.1.0.0", "contained-holder": ["PORT-1.1.1.8", "PORT-1.1.1.7", "PORT-1.1.1.6", "PORT-1.1.1.5"], "date": "2015-08-17T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.1.8", "part-type-id": "1AB376720002", "model-identifier": "NGI7AMLMAA", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/CORE-MAIN/a2.module#8", "type-name": "a2.module", "serial": "01T441601301", "id": "robot_sim_2_equipment/a2.module-1.1.1.8", "parent-uuid": "CARD-1.1.1.0", "contained-holder": ["SUBRACK-1.18.0.0"], "date": "2010-02-05T00:00:00.0Z" },
+ { "manufacturer-identifier": "SAN", "version": "234", "uuid": "CARD-1.1.5.0", "part-type-id": "part-number-12", "model-identifier": "model-id-12", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module", "type-name": "p8.module", "serial": "africa", "id": "robot_sim_2_equipment/CARD-1.1.5.0", "parent-uuid": "SHELF-1.1.0.0", "contained-holder": ["PORT-1.1.5.6", "PORT-1.1.5.5", "PORT-1.1.5.8", "PORT-1.1.5.7"], "date": "2013-10-21T00:00:00.0Z" },
+ { "manufacturer-identifier": "", "version": "", "uuid": "a2.module-1.1.5.6", "part-type-id": "", "model-identifier": "", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module/a2.module#6", "type-name": "a2.module", "serial": "", "id": "robot_sim_2_equipment/a2.module-1.1.5.6", "parent-uuid": "CARD-1.1.5.0", "contained-holder": ["SUBRACK-1.56.0.0"] }, { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "MWR-ng", "uuid": "IDU-1.65.0.0", "part-type-id": "3DB76047BAAA02", "model-identifier": "model-id-s3s", "tree-level": 0, "node-id": "robot_sim_2_equipment", "description": "MWR-ng Dir#6.5-Ch#1", "type-name": "MWR-ng", "serial": "WAUZZI", "id": "robot_sim_2_equipment/IDU-1.65.0.0", "parent-uuid": "network-element", "contained-holder": ["PORT-1.65.1.4", "PORT-1.65.1.2"], "date": "2014-01-16T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.65.1.2", "part-type-id": "3EM23141AD01", "model-identifier": "CRPQABVFAA", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "MWR#65Ch#1/a2.moduletraff", "type-name": "a2.module", "serial": "310330008", "id": "robot_sim_2_equipment/a2.module-1.65.1.2", "parent-uuid": "IDU-1.65.0.0", "date": "2013-04-13T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.5.5", "part-type-id": "3EM23141AD01", "model-identifier": "CRPQABVFAA", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/p8.module/a2.module#5", "type-name": "a2.module", "serial": "310330015", "id": "robot_sim_2_equipment/a2.module-1.1.5.5", "parent-uuid": "CARD-1.1.5.0", "contained-holder": ["SUBRACK-1.55.0.0"], "date": "2013-04-13T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "unknown", "uuid": "CARD-1.1.8.0", "part-type-id": "unknown", "model-identifier": "model-id-s3s", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/DS3", "type-name": "p4.module", "serial": "sd-dsa-eqw", "id": "robot_sim_2_equipment/CARD-1.1.8.0", "parent-uuid": "SHELF-1.1.0.0", "date": "2008-10-21T00:00:00.0Z" },
+ { "manufacturer-identifier": "CIT", "version": "wind", "uuid": "CARD-1.1.9.0", "part-type-id": "party-yea", "model-identifier": "model-id-s3s", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/wind", "type-name": "wind", "serial": "proto-type", "id": "robot_sim_2_equipment/CARD-1.1.9.0", "parent-uuid": "SHELF-1.1.0.0", "date": "2007-02-19T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.55.1.2", "part-type-id": "3EM23141AD01", "model-identifier": "CRPQABVFAA", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "MWR#55Ch#1/a2.moduletraff", "type-name": "a2.module", "serial": "310330015", "id": "robot_sim_2_equipment/a2.module-1.55.1.2", "parent-uuid": "IDU-1.55.0.0", "date": "2013-04-13T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "SHELF-1.1.0.0", "part-type-id": "Partnumber", "model-identifier": "model-id", "tree-level": 0, "node-id": "robot_sim_2_equipment", "description": "WS-8", "type-name": "WS-8", "serial": "Serial1", "id": "robot_sim_2_equipment/SHELF-1.1.0.0", "parent-uuid": "network-element", "contained-holder": ["SLOT-1.1.9.0", "SLOT-1.1.7.0", "SLOT-1.1.8.0", "SLOT-1.1.5.0", "SLOT-1.1.6.0", "SLOT-1.1.3.0", "SLOT-1.1.4.0", "SLOT-1.1.2.0", "SLOT-1.1.1.0"], "date": "2017-09-09T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "MWR-ng", "uuid": "IDU-1.55.0.0", "part-type-id": "3DB76047BAAA02", "model-identifier": "model-id-s3s", "tree-level": 0, "node-id": "robot_sim_2_equipment", "description": "MWR-ng Dir#5.5-Ch#1", "type-name": "MWR-ng", "serial": "Serie2017-14", "id": "robot_sim_2_equipment/IDU-1.55.0.0", "parent-uuid": "network-element", "contained-holder": ["PORT-1.55.1.2", "PORT-1.55.1.4"], "date": "2014-01-15T00:00:00.0Z" },
+ { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "2017", "uuid": "CARD-1.65.1.4", "part-type-id": "partNo2017-12", "model-identifier": "model-id-s3s", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "MWR#55Ch#0/RxDiv", "type-name": "RxDiv", "serial": "Serie2017-13", "id": "robot_sim_2_equipment/CARD-1.65.1.4", "parent-uuid": "IDU-1.65.0.0", "date": "2014-01-08T00:00:00.0Z" }, { "manufacturer-identifier": "ONF-Wireless-Transport", "version": "a2.module-newest", "uuid": "a2.module-1.1.1.7", "part-type-id": "1AB187280031", "model-identifier": "mod2", "tree-level": 2, "node-id": "robot_sim_2_equipment", "description": "WS/CORE-MAIN/a2.module#7", "type-name": "a2.module", "serial": "91T403003322", "id": "robot_sim_2_equipment/a2.module-1.1.1.7", "parent-uuid": "CARD-1.1.1.0", "contained-holder": ["SUBRACK-1.17.0.0"], "date": "2009-01-19T00:00:00.0Z" },
+ { "manufacturer-identifier": "CIT", "version": "p1.module", "uuid": "CARD-1.1.7.0", "part-type-id": "part-number-s3s", "model-identifier": "model-id-s3s", "tree-level": 1, "node-id": "robot_sim_2_equipment", "description": "WS/DS1", "type-name": "p1.module_A", "serial": "serial-number-s3s", "id": "robot_sim_2_equipment/CARD-1.1.7.0", "parent-uuid": "SHELF-1.1.0.0", "date": "2007-08-27T00:00:00.0Z" },
+ { "manufacturer-identifier": "", "version": "extrem-hyper", "uuid": "ODU-1.56.0.0", "part-type-id": "", "model-identifier": "", "tree-level": 0, "node-id": "robot_sim_2_equipment", "description": "MWR-hyper Dir#5.6-Ch#1", "type-name": "MWR-hyper", "serial": "", "id": "robot_sim_2_equipment/ODU-1.56.0.0", "parent-uuid": "network-element", "contained-holder": ["PORT-1.56.1.3", "PORT-1.56.1.4", "PORT-1.56.1.2"] }
+];
+
+const deleay = (time: number) => () => new Promise<number>(resolve => setTimeout(resolve, time, time));
+
+const getTreeElements = (searchTerm: string | null, treeLevel: number = 0, parentUUID: string | null = null): [InventoryTreeNode, boolean] => {
+ const elements = (data.filter(e => e["tree-level"] === treeLevel && (!parentUUID || e["parent-uuid"] === parentUUID)) || [])
+ let elementMatch = false;
+ const treeeNode = elements.reduce<InventoryTreeNode>((acc, cur) => {
+ const [children, childMatch] = getTreeElements(searchTerm, treeLevel + 1, cur["node-id"]);
+ const isMatch = searchTerm ? Object.keys(cur).some(k => String((cur as any)[k]).indexOf(searchTerm)) : false;
+ elementMatch = elementMatch || isMatch || childMatch;
+ if (!searchTerm || isMatch || childMatch) {
+ acc[cur["node-id"]] = {
+ label: cur["node-id"],
+ children: children,
+ isMatch: false,
+ };
+ }
+ return acc;
+ }, {});
+
+ return [treeeNode, elementMatch]
+};
+
+export const getTree = async (searchTerm: string | null = null) : Promise<InventoryTreeNode> => {
+ await deleay(600);
+ const [node] = getTreeElements(searchTerm);
+ return node;
+};
+
+export const getElement = async (id: string ): Promise<InventoryType | undefined> => {
+ await deleay(600);
+ const res = data.find(e => e.id === id);
+ return res && convertPropertyNames(res, replaceHyphen) as unknown as InventoryType;
+};
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
index 9d747415f..c6b6c91cb 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts
@@ -16,6 +16,7 @@
* ============LICENSE_END==========================================================================
*/
export { HitEntry, Result } from '../../../../framework/src/models';
+
export type InventoryType = {
treeLevel: number;
parentUuid: string;
@@ -32,3 +33,13 @@ export type InventoryType = {
modelIdentifier: string;
typeName: string;
}
+
+export type InventoryTreeNode = {
+ [key: string]: {
+ label: string;
+ children?: InventoryTreeNode;
+ isMatch?: boolean;
+ ownSeverity?: string;
+ childrenSeveritySummary?: string;
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts b/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts
new file mode 100644
index 000000000..252d6d425
--- /dev/null
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts
@@ -0,0 +1,37 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+import { requestRest } from '../../../../framework/src/services/restService';
+
+import { InventoryTreeNode, InventoryType } from '../models/inventory';
+import { getTree, getElement } from '../fakeData';
+
+/**
+ * Represents a web api accessor service for all maintenence entries related actions.
+ */
+class InventoryService {
+ public async getInventoryTree(searchTerm?: string): Promise<InventoryTreeNode> {
+ return await getTree(searchTerm);
+ }
+
+ public async getInventoryEntry(id: string): Promise<InventoryType| undefined> {
+ return await getElement(id);
+ }
+
+}
+
+export const inventoryService = new InventoryService(); \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
index bd182ed5d..b63f628a3 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
+++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx
@@ -16,14 +16,33 @@
* ============LICENSE_END==========================================================================
*/
import * as React from "react";
+import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles';
import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect';
import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { TreeView, TreeItem, TreeViewCtorType } from '../../../../framework/src/components/material-ui/treeView';
import { InventoryType } from '../models/inventory';
import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
import { createInventoryElementsProperties, createInventoryElementsActions } from "../handlers/inventoryElementsHandler";
+const styles = (theme: Theme) => createStyles({
+ root: {
+ flex: "1 0 0%",
+ display: "flex",
+ flexDirection: "row",
+ },
+ tree: {
+ flex: "1 0 0%",
+ minWidth: "250px",
+ padding: `0px ${theme.spacing(1)}px`
+ },
+ details: {
+ flex: "5 0 0%",
+ padding: `0px ${theme.spacing(1)}px`
+ }
+});
+
const InventoryTable = MaterialTable as MaterialTableCtorType<InventoryType & {_id: string}>;
const mapProps = (state: IApplicationStoreState) => ({
@@ -35,9 +54,28 @@ const mapDispatch = (dispatcher: IDispatcher) => ({
inventoryElementsActions: createInventoryElementsActions(dispatcher.dispatch)
});
-class DashboardComponent extends React.Component<Connect<typeof mapProps, typeof mapDispatch>> {
+const SampleTree = TreeView as any as TreeViewCtorType<string>;
+
+
+type TreeDemoItem = TreeItem<string>;
+
+const treeData: TreeDemoItem[] = [
+ {
+ content: "Erste Ebene", children: [
+ {
+ content: "Zweite Ebene", children: [
+ { content: "Dritte Ebene" },
+ ]
+ },
+ { content: "Zweite Ebene 2" },
+ ]
+ },
+ { content: "Erste Ebene 3" },
+];
+
+class DashboardComponent extends React.Component<& WithStyles<typeof styles> & Connect<typeof mapProps, typeof mapDispatch>> {
render() {
- return <InventoryTable title="Inventory" idProperty="_id" columns={[
+ return <InventoryTable stickyHeader title="Inventory" idProperty="_id" columns={[
{ property: "nodeId", title: "Node Name" },
{ property: "manufacturerIdentifier", title: "Manufacturer" },
{ property: "parentUuid", title: "Parent" },
@@ -60,5 +98,5 @@ class DashboardComponent extends React.Component<Connect<typeof mapProps, typeof
}
}
-export const Dashboard = connect(mapProps, mapDispatch)(DashboardComponent);
+export const Dashboard = connect(mapProps, mapDispatch)(withStyles(styles)(DashboardComponent));
export default Dashboard; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js b/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
index 426763803..889bb4d8e 100644
--- a/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
+++ b/sdnr/wt/odlux/apps/inventoryApp/webpack.config.js
@@ -126,11 +126,14 @@ module.exports = (env) => {
colors: true
},
proxy: {
-
"/oauth2/": {
target: "http://localhost:48181",
secure: false
},
+ "/yang-schema/": {
+ target: "http://localhost:48181",
+ secure: false
+ },
"/database/": {
target: "http://localhost:48181",
secure: false
@@ -143,14 +146,13 @@ module.exports = (env) => {
target: "http://localhost:48181",
secure: false
},
- "/websocket/": {
+ "/websocket": {
target: "http://localhost:48181",
ws: true,
- changeOrigin: true,
+ changeOrigin: false,
secure: false
}
}
-
}
}];
}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx
index f557e5399..350bac221 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx
@@ -37,7 +37,7 @@ import { MaintenenceEntry, spoofSymbol } from '../models/maintenenceEntryType';
import EditMaintenenceEntryDialog, { EditMaintenenceEntryDialogMode } from '../components/editMaintenenceEntryDialog';
import { convertToLocaleString } from '../utils/timeUtils';
-import { createmaintenanceEntriesActions, createmaintenanceEntriesProperties,maintenanceEntriesReloadAction } from '../handlers/maintenenceEntriesHandler';
+import { createmaintenanceEntriesActions, createmaintenanceEntriesProperties, maintenanceEntriesReloadAction } from '../handlers/maintenenceEntriesHandler';
const styles = (theme: Theme) => createStyles({
button: {
@@ -60,7 +60,7 @@ const mapProps = (state: IApplicationStoreState) => ({
const mapDispatcher = (dispatcher: IDispatcher) => ({
maintenanceEntriesActions: createmaintenanceEntriesActions(dispatcher.dispatch),
- onLoadMaintenanceEntries: async() => {
+ onLoadMaintenanceEntries: async () => {
await dispatcher.dispatch(maintenanceEntriesReloadAction)
}
});
@@ -104,8 +104,8 @@ class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentP
this.setState({
maintenenceEntryToEdit: {
...emptyMaintenenceEntry,
- start: convertToLocaleString(startTime),
- end: convertToLocaleString(endTime),
+ start: convertToLocaleString(startTime),
+ end: convertToLocaleString(endTime),
},
maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.AddMaintenenceEntry
});
@@ -114,13 +114,13 @@ class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentP
const now = new Date().valueOf();
return (
<>
- <MaintenenceEntriesTable title={"Maintenance"} customActionButtons={[addMaintenenceEntryAction]} columns={
+ <MaintenenceEntriesTable stickyHeader title={"Maintenance"} customActionButtons={[addMaintenenceEntryAction]} columns={
[
{ property: "nodeId", title: "Node Name", type: ColumnType.text },
{
property: "notifications", title: "Notification", width: 50, align: "center", type: ColumnType.custom, customControl: ({ rowData }) => (
rowData.active && (Date.parse(rowData.start).valueOf() <= now) && (Date.parse(rowData.end).valueOf() >= now) && <FontAwesomeIcon icon={faBan} /> || null
- )
+ )
},
{ property: "active", title: "Activation State", type: ColumnType.boolean, labels: { "true": "active", "false": "not active" }, },
{ property: "start", title: "Start Date (UTC)", type: ColumnType.text },
@@ -140,7 +140,7 @@ class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentP
)
},
]
- } idProperty={'_id'}{...this.props.maintenanceEntriesActions} {...this.props.maintenanceEntriesProperties} asynchronus > </MaintenenceEntriesTable>
+ } idProperty={'_id'}{...this.props.maintenanceEntriesActions} {...this.props.maintenanceEntriesProperties} asynchronus > </MaintenenceEntriesTable>
<EditMaintenenceEntryDialog initialMaintenenceEntry={this.state.maintenenceEntryToEdit} mode={this.state.maintenenceEntryEditorMode}
onClose={this.onCloseEditMaintenenceEntryDialog} />
</>
@@ -160,8 +160,8 @@ class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentP
this.setState({
maintenenceEntryToEdit: {
...entry,
- start: convertToLocaleString(startTime),
- end: convertToLocaleString(endTime),
+ start: convertToLocaleString(startTime),
+ end: convertToLocaleString(endTime),
},
maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
});
@@ -175,8 +175,8 @@ class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentP
this.setState({
maintenenceEntryToEdit: {
...entry,
- start: convertToLocaleString(startTime),
- end: convertToLocaleString(endTime),
+ start: convertToLocaleString(startTime),
+ end: convertToLocaleString(endTime),
},
maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode.EditMaintenenceEntry
});
@@ -190,7 +190,7 @@ class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentP
this.setState({
maintenenceEntryToEdit: {
...entry,
- ...(entry.start && endTime)
+ ...(entry.start && endTime)
? { start: convertToLocaleString(entry.start), end: convertToLocaleString(entry.end) }
: { start: convertToLocaleString(startTime), end: convertToLocaleString(endTime) }
},
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
index 945e13507..d422a0c3b 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
@@ -161,7 +161,7 @@ class MediatorApplicationComponent extends React.Component<MediatorApplicationCo
this.props.isReachable ?
- <MediatorServerConfigurationsTable title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[
+ <MediatorServerConfigurationsTable stickyHeader title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[
{ property: "Name", title: "Mediator", type: ColumnType.text },
{ property: "Status", title: "Status", type: ColumnType.custom, customControl: ({ rowData }) => rowData.pid ? (<span>Running</span>) : (<span>Stopped</span>) },
{ property: "DeviceIp", title: "IP Adress", type: ColumnType.text },
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
index a5b34a2dc..aaade65db 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
@@ -94,7 +94,7 @@ class MediatorServerSelectionComponent extends React.Component<MediatorServerSel
};
return (
<>
- <MediatorServersTable title={"Mediator"} customActionButtons={[addMediatorServerActionButton]} idProperty={"id"}
+ <MediatorServersTable stickyHeader title={"Mediator"} customActionButtons={[addMediatorServerActionButton]} idProperty={"id"}
{...this.props.mediatorServersActions} {...this.props.mediatorServersProperties} columns={[
{ property: "name", title: "Name", type: ColumnType.text },
{ property: "url", title: "Url", type: ColumnType.text },
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
index 375617593..a678ed78c 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
@@ -50,6 +50,18 @@ export class SetInitialLoadedAction extends BaseAction {
}
}
+export class NoLtpsFoundAction extends BaseAction {
+ constructor() {
+ super();
+ }
+}
+
+export class ResetLtpsAction extends BaseAction {
+ constructor() {
+ super();
+ }
+}
+
/**
* Represents an asynchronous thunk action to load available distinctLtps by networkElement from the database and set the returned first Ltp as default.
@@ -65,6 +77,10 @@ export const loadDistinctLtpsbyNetworkElementAsync = (networkElement: string, se
if (distinctLtps) {
const ltps = getDistinctLtps(distinctLtps, selectedLtp, selectFirstLtp, resetLtp);
dispatch(new AllAvailableLtpsLoadedAction(ltps));
+ } else {
+ if (resetLtp)
+ resetLtp();
+ dispatch(new NoLtpsFoundAction());
}
}).catch(error => {
dispatch(new AllAvailableLtpsLoadedAction(null, error));
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts
index 1f53a5806..0efaaae92 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts
@@ -1,3 +1,21 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ * ============LICENSE_END==========================================================================
+ */
+
import { Action } from "../../../../framework/src/flux/action";
import { currentViewType } from "../models/toggleDataType";
@@ -12,4 +30,10 @@ export class ResetAllSubViewsAction extends Action {
constructor() {
super();
}
+}
+
+export class SetFilterVisibility extends Action {
+ constructor(public currentView: currentViewType, public isVisible: boolean) {
+ super();
+ }
} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
index c62698630..ca00d8214 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
@@ -29,17 +29,19 @@ import { createAdaptiveModulationProperties, createAdaptiveModulationActions } f
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
import ToggleContainer from './toggleContainer';
-import { SetSubViewAction } from '../actions/toggleActions';
+import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
const mapProps = (state: IApplicationStoreState) => ({
adaptiveModulationProperties: createAdaptiveModulationProperties(state),
- currentView: state.performanceHistory.subViews.adaptiveModulation,
-
+ currentView: state.performanceHistory.subViews.adaptiveModulation.subView,
+ isFilterVisible: state.performanceHistory.subViews.adaptiveModulation.isFilterVisible,
+ existingFilter: state.performanceHistory.adaptiveModulation.filter
});
const mapDisp = (dispatcher: IDispatcher) => ({
adaptiveModulationActions: createAdaptiveModulationActions(dispatcher.dispatch),
setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("adaptiveModulation", value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("adaptiveModulation", value)) },
});
type AdaptiveModulationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -52,6 +54,11 @@ const AdaptiveModulationTable = MaterialTable as MaterialTableCtorType<AdaptiveM
* The Component which gets the adaptiveModulation data from the database based on the selected time period.
*/
class AdaptiveModulationComponent extends React.Component<AdaptiveModulationComponentProps>{
+
+ onToggleFilterButton = () => {
+ this.props.toggleFilterButton(!this.props.isFilterVisible);
+ }
+
onChange = (value: "chart" | "table") => {
this.props.setSubView(value);
}
@@ -66,10 +73,7 @@ class AdaptiveModulationComponent extends React.Component<AdaptiveModulationComp
{ property: "scannerId", title: "Scanner ID", type: ColumnType.text },
{ property: "timeStamp", title: "End Time", type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
- const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
- return <div >{suspectIntervalFlag} </div>
- }
+ property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
}];
chartPagedData.datasets.forEach(ds => {
@@ -78,9 +82,9 @@ class AdaptiveModulationComponent extends React.Component<AdaptiveModulationComp
return (
<>
- <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.adaptiveModulationProperties.filter} onFilterChanged={this.props.adaptiveModulationActions.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
{lineChart(chartPagedData)}
- <AdaptiveModulationTable idProperty={"_id"} columns={adaptiveModulationColumns} {...properties} {...actions} />
+ <AdaptiveModulationTable stickyHeader idProperty={"_id"} columns={adaptiveModulationColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx
new file mode 100644
index 000000000..280a1dac8
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx
@@ -0,0 +1,50 @@
+import * as React from 'react';
+import { makeStyles, TextField, Typography, Select, MenuItem, FormControl, InputLabel } from '@material-ui/core';
+
+const styles = makeStyles({
+ filterInput: {
+ marginRight: "15px"
+ },
+ filterContainer: {
+ marginLeft: "90px"
+ }
+});
+
+type filterProps = { isVisible: boolean, onFilterChanged: (property: string, filterTerm: string) => void, filters: any };
+//put chart visibility into redux
+const ChartFilter: React.FunctionComponent<filterProps> = (props) => {
+
+ //get filter from redux state (just pass da object?), onfilterchange
+ const classes = styles();
+
+ return (
+ <>
+ {
+ props.isVisible &&
+ <div className={classes.filterContainer}>
+ <TextField className={classes.filterInput} label="Radio Signal" value={props.filters.radioSignalId || ''} onChange={(event) => props.onFilterChanged("radioSignalId", event.target.value)} InputLabelProps={{
+ shrink: true,
+ }} />
+ <TextField className={classes.filterInput} label="Scanner ID" value={props.filters.scannerId || ''} onChange={(event) => props.onFilterChanged("scannerId", event.target.value)} InputLabelProps={{
+ shrink: true,
+ }} />
+ <TextField className={classes.filterInput} label="End Time" value={props.filters.timeStamp || ''} onChange={(event) => props.onFilterChanged("timeStamp", event.target.value)} InputLabelProps={{
+ shrink: true,
+ }} />
+ <FormControl>
+ <InputLabel id="suspect-interval-label" shrink>Suspect Interval</InputLabel>
+
+ <Select labelId="suspect-interval-label" value={props.filters.suspectIntervalFlag || ''} onChange={(event) => props.onFilterChanged("suspectIntervalFlag", event.target.value as string)}>
+ <MenuItem value={undefined}>None</MenuItem>
+ <MenuItem value={"true"}>true</MenuItem>
+ <MenuItem value={"false"}>false</MenuItem>
+ </Select>
+ </FormControl>
+ </ div>
+ }
+ </>
+ )
+
+}
+
+export default ChartFilter; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
index 7489757f5..a8c6ed78d 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
@@ -28,19 +28,22 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes';
import { createCrossPolarDiscriminationProperties, createCrossPolarDiscriminationActions } from '../handlers/crossPolarDiscriminationHandler';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
-import { SetSubViewAction } from '../actions/toggleActions';
+import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
import ToggleContainer from './toggleContainer';
const mapProps = (state: IApplicationStoreState) => ({
crossPolarDiscriminationProperties: createCrossPolarDiscriminationProperties(state),
- currentView: state.performanceHistory.subViews.CPD,
+ currentView: state.performanceHistory.subViews.CPD.subView,
+ isFilterVisible: state.performanceHistory.subViews.CPD.isFilterVisible,
+ existingFilter: state.performanceHistory.crossPolarDiscrimination.filter
});
const mapDisp = (dispatcher: IDispatcher) => ({
crossPolarDiscriminationActions: createCrossPolarDiscriminationActions(dispatcher.dispatch),
setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("CPD", value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("CPD", value)) },
});
type CrossPolarDiscriminationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -54,6 +57,10 @@ const CrossPolarDiscriminationTable = MaterialTable as MaterialTableCtorType<Cro
*/
class CrossPolarDiscriminationComponent extends React.Component<CrossPolarDiscriminationComponentProps>{
+ onToggleFilterButton = () => {
+ this.props.toggleFilterButton(!this.props.isFilterVisible);
+ }
+
onChange = (value: "chart" | "table") => {
this.props.setSubView(value);
}
@@ -69,10 +76,7 @@ class CrossPolarDiscriminationComponent extends React.Component<CrossPolarDiscri
{ property: "scannerId", title: "Scanner ID", type: ColumnType.text },
{ property: "timeStamp", title: "End Time", type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
- const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
- return <div >{suspectIntervalFlag} </div>
- }
+ property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
}
];
@@ -81,9 +85,9 @@ class CrossPolarDiscriminationComponent extends React.Component<CrossPolarDiscri
});
return (
<>
- <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.crossPolarDiscriminationProperties.filter} onFilterChanged={this.props.crossPolarDiscriminationActions.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
{lineChart(chartPagedData)}
- <CrossPolarDiscriminationTable idProperty={"_id"} columns={cpdColumns} {...properties} {...actions} />
+ <CrossPolarDiscriminationTable stickyHeader idProperty={"_id"} columns={cpdColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx
index 8327ec4ed..b0aebd208 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx
@@ -17,7 +17,7 @@
*/
import * as React from 'react';
-import { MenuItem, Select, FormControl } from '@material-ui/core';
+import { MenuItem, Select, FormControl, Typography } from '@material-ui/core';
import { makeStyles } from '@material-ui/core/styles';
import { LtpIds } from 'models/availableLtps';
import { Loader } from '../../../../framework/src/components/material-ui';
@@ -43,10 +43,11 @@ const useStyles = makeStyles(theme => ({
"display": "flex",
"alignItems": "center",
"justifyContent": "center",
+ flexDirection: "column"
}
}));
-type LtpSelectionProps = { selectedNE: string, finishedLoading: boolean, selectedLtp: string, availableLtps: LtpIds[], onChangeLtp(event: React.ChangeEvent<HTMLSelectElement>): void, selectedTimePeriod: string, onChangeTimePeriod(event: React.ChangeEvent<HTMLSelectElement>): void };
+type LtpSelectionProps = { selectedNE: string, error?: string, finishedLoading: boolean, selectedLtp: string, availableLtps: LtpIds[], onChangeLtp(event: React.ChangeEvent<HTMLSelectElement>): void, selectedTimePeriod: string, onChangeTimePeriod(event: React.ChangeEvent<HTMLSelectElement>): void };
export const LtpSelection = (props: LtpSelectionProps) => {
const classes = useStyles();
@@ -69,18 +70,29 @@ export const LtpSelection = (props: LtpSelectionProps) => {
</Select>
</FormControl>
{
- !props.finishedLoading &&
+ !props.finishedLoading && !props.error &&
<div className={classes.center}>
<Loader />
<h3>Collecting Data ...</h3>
</div>
}
{
- props.selectedLtp === "-1" && props.finishedLoading &&
+ props.finishedLoading && props.error &&
<div className={classes.center}>
- <h3>Please select a LTP</h3>
+ <h3>Data couldn't be loaded</h3>
+ <Typography variant="body1">{props.error}</Typography>
</div>
}
+ {
+ props.selectedLtp === "-1" && props.finishedLoading && !props.error && (props.availableLtps.length > 0 ?
+ <div className={classes.center}>
+ <h3>Please select a LTP</h3>
+ </div>
+ :
+ <div className={classes.center}>
+ <h3>No performance data found</h3>
+ </div>)
+ }
</>)
}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
index d0caa6fd6..0a4f03273 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
@@ -28,16 +28,19 @@ import { createPerformanceDataProperties, createPerformanceDataActions } from '.
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
import ToggleContainer from './toggleContainer';
-import { SetSubViewAction } from '../actions/toggleActions';
+import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
const mapProps = (state: IApplicationStoreState) => ({
performanceDataProperties: createPerformanceDataProperties(state),
- currentView: state.performanceHistory.subViews.performanceDataSelection,
+ currentView: state.performanceHistory.subViews.performanceData.subView,
+ isFilterVisible: state.performanceHistory.subViews.performanceData.isFilterVisible,
+ existingFilter: state.performanceHistory.performanceData.filter
});
const mapDisp = (dispatcher: IDispatcher) => ({
performanceDataActions: createPerformanceDataActions(dispatcher.dispatch),
setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("performanceData", value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("performanceData", value)) }
});
type PerformanceDataComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -51,8 +54,8 @@ const PerformanceDataTable = MaterialTable as MaterialTableCtorType<PerformanceD
*/
class PerformanceDataComponent extends React.Component<PerformanceDataComponentProps>{
- onChange = (value: "chart" | "table") => {
- this.props.setSubView(value);
+ onToggleFilterButton = () => {
+ this.props.toggleFilterButton(!this.props.isFilterVisible);
}
render(): JSX.Element {
@@ -65,10 +68,7 @@ class PerformanceDataComponent extends React.Component<PerformanceDataComponentP
{ property: "scannerId", title: "Scanner ID", type: ColumnType.text },
{ property: "timeStamp", title: "End Time", type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
- const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
- return <div >{suspectIntervalFlag} </div>
- }
+ property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
}
];
@@ -77,9 +77,9 @@ class PerformanceDataComponent extends React.Component<PerformanceDataComponentP
});
return (
<>
- <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ <ToggleContainer onToggleFilterButton={() => this.props.toggleFilterButton(!this.props.isFilterVisible)} existingFilter={this.props.existingFilter} onFilterChanged={this.props.performanceDataActions.onFilterChanged} selectedValue={this.props.currentView} showFilter={this.props.isFilterVisible} onChange={this.props.setSubView}>
{lineChart(chartPagedData)}
- <PerformanceDataTable idProperty={"_id"} columns={performanceColumns} {...properties} {...actions} />
+ <PerformanceDataTable stickyHeader idProperty={"_id"} columns={performanceColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
index 4b0a835d4..ae729306b 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
@@ -28,19 +28,20 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes';
import { createReceiveLevelProperties, createReceiveLevelActions } from '../handlers/receiveLevelHandler';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
-import { SetSubViewAction } from '../actions/toggleActions';
+import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
import ToggleContainer from './toggleContainer';
const mapProps = (state: IApplicationStoreState) => ({
receiveLevelProperties: createReceiveLevelProperties(state),
- currentView: state.performanceHistory.subViews.receiveLevelDataSelection,
-
+ currentView: state.performanceHistory.subViews.receiveLevel.subView,
+ isFilterVisible: state.performanceHistory.subViews.receiveLevel.isFilterVisible,
+ existingFilter: state.performanceHistory.receiveLevel.filter
});
const mapDisp = (dispatcher: IDispatcher) => ({
receiveLevelActions: createReceiveLevelActions(dispatcher.dispatch),
setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("receiveLevel", value)),
-
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("receiveLevel", value)) },
});
type ReceiveLevelComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -54,6 +55,11 @@ const ReceiveLevelTable = MaterialTable as MaterialTableCtorType<ReceiveLevelDat
*/
class ReceiveLevelComponent extends React.Component<ReceiveLevelComponentProps>{
+ onToggleFilterButton = () => {
+ this.props.toggleFilterButton(!this.props.isFilterVisible);
+ }
+
+
onChange = (value: "chart" | "table") => {
this.props.setSubView(value);
}
@@ -68,10 +74,7 @@ class ReceiveLevelComponent extends React.Component<ReceiveLevelComponentProps>{
{ property: "scannerId", title: "Scanner ID", type: ColumnType.text },
{ property: "timeStamp", title: "End Time", type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
- const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
- return <div >{suspectIntervalFlag} </div>
- }
+ property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
}
];
@@ -81,9 +84,9 @@ class ReceiveLevelComponent extends React.Component<ReceiveLevelComponentProps>{
return (
<>
- <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.receiveLevelProperties.filter} onFilterChanged={this.props.receiveLevelActions.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
{lineChart(chartPagedData)}
- <ReceiveLevelTable idProperty={"_id"} columns={receiveLevelColumns} {...properties} {...actions} />
+ <ReceiveLevelTable stickyHeader idProperty={"_id"} columns={receiveLevelColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
index ba480d57d..00eba5fe3 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
@@ -28,17 +28,20 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes';
import { createSignalToInterferenceProperties, createSignalToInterferenceActions } from '../handlers/signalToInterferenceHandler';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
-import { SetSubViewAction } from '../actions/toggleActions';
+import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
import ToggleContainer from './toggleContainer';
const mapProps = (state: IApplicationStoreState) => ({
signalToInterferenceProperties: createSignalToInterferenceProperties(state),
- currentView: state.performanceHistory.subViews.SINR,
+ currentView: state.performanceHistory.subViews.SINR.subView,
+ isFilterVisible: state.performanceHistory.subViews.SINR.isFilterVisible,
+ existingFilter: state.performanceHistory.signalToInterference.filter
});
const mapDisp = (dispatcher: IDispatcher) => ({
signalToInterferenceActions: createSignalToInterferenceActions(dispatcher.dispatch),
setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("SINR", value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("SINR", value)) },
});
type SignalToInterferenceComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -52,6 +55,10 @@ const SignalToInterferenceTable = MaterialTable as MaterialTableCtorType<SignalT
*/
class SignalToInterferenceComponent extends React.Component<SignalToInterferenceComponentProps>{
+ onToggleFilterButton = () => {
+ this.props.toggleFilterButton(!this.props.isFilterVisible);
+ }
+
onChange = (value: "chart" | "table") => {
this.props.setSubView(value);
}
@@ -67,10 +74,7 @@ class SignalToInterferenceComponent extends React.Component<SignalToInterference
{ property: "scannerId", title: "Scanner ID", type: ColumnType.text },
{ property: "timeStamp", title: "End Time", type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
- const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
- return <div >{suspectIntervalFlag} </div>
- }
+ property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
}
];
@@ -79,9 +83,9 @@ class SignalToInterferenceComponent extends React.Component<SignalToInterference
});
return (
<>
- <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.signalToInterferenceProperties.filter} onFilterChanged={this.props.signalToInterferenceActions.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
{lineChart(chartPagedData)}
- <SignalToInterferenceTable idProperty={"_id"} columns={sinrColumns} {...properties} {...actions}
+ <SignalToInterferenceTable stickyHeader idProperty={"_id"} columns={sinrColumns} {...properties} {...actions}
/>
</ToggleContainer>
</>
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
index 28f75d84c..c0d12ee47 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
@@ -29,16 +29,20 @@ import { createTemperatureProperties, createTemperatureActions } from '../handle
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
import ToggleContainer from './toggleContainer';
-import { SetSubViewAction } from '../actions/toggleActions';
+import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
const mapProps = (state: IApplicationStoreState) => ({
temperatureProperties: createTemperatureProperties(state),
- currentView: state.performanceHistory.subViews.temperatur,
+ currentView: state.performanceHistory.subViews.temperatur.subView,
+ isFilterVisible: state.performanceHistory.subViews.temperatur.isFilterVisible,
+ existingFilter: state.performanceHistory.temperature.filter
});
const mapDisp = (dispatcher: IDispatcher) => ({
temperatureActions: createTemperatureActions(dispatcher.dispatch),
setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("Temp", value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("Temp", value)) },
+
});
type TemperatureComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -52,6 +56,11 @@ const TemperatureTable = MaterialTable as MaterialTableCtorType<TemperatureDataT
*/
class TemperatureComponent extends React.Component<TemperatureComponentProps>{
+ onToggleFilterButton = () => {
+ this.props.toggleFilterButton(!this.props.isFilterVisible);
+ }
+
+
onChange = (value: "chart" | "table") => {
this.props.setSubView(value);
}
@@ -66,10 +75,7 @@ class TemperatureComponent extends React.Component<TemperatureComponentProps>{
{ property: "scannerId", title: "Scanner ID", type: ColumnType.text },
{ property: "timeStamp", title: "End Time", type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
- const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
- return <div >{suspectIntervalFlag} </div>
- }
+ property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
}
];
@@ -79,9 +85,9 @@ class TemperatureComponent extends React.Component<TemperatureComponentProps>{
return (
<>
- <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ <ToggleContainer onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.temperatureProperties.filter} onFilterChanged={this.props.temperatureActions.onFilterChanged} selectedValue={this.props.currentView} onChange={this.onChange}>
{lineChart(chartPagedData)}
- <TemperatureTable idProperty={"_id"} columns={temperatureColumns} {...properties} {...actions} />
+ <TemperatureTable stickyHeader idProperty={"_id"} columns={temperatureColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
index 97a2006f7..618dddfc8 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
@@ -23,16 +23,34 @@ import BarChartIcon from '@material-ui/icons/BarChart';
import TableChartIcon from '@material-ui/icons/TableChart';
import { makeStyles } from '@material-ui/core';
import Tooltip from '@material-ui/core/Tooltip';
+import ChartFilter from './chartFilter'
+import FilterListIcon from '@material-ui/icons/FilterList';
const styles = makeStyles({
- toggleButton: {
+ toggleButtonContainer: {
+ display: "flex",
alignItems: "center",
justifyContent: "center",
padding: "10px",
+ },
+ subViewGroup: {
+ padding: "10px"
+ },
+ filterGroup: {
+ marginLeft: "10px"
}
});
-type toggleProps = { selectedValue: string, onChange(value: string): void };
+type filterType = {
+ onRefresh: () => void;
+ onHandleRequestSort: (orderBy: string) => void;
+ onToggleFilter: () => void;
+ onFilterChanged: (property: string, filterTerm: string) => void;
+ onHandleChangePage: (page: number) => void;
+ onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void;
+};
+
+type toggleProps = { selectedValue: string, onChange(value: string): void, showFilter: boolean, onToggleFilterButton(): void, onFilterChanged: (property: string, filterTerm: string) => void, existingFilter: any };
const ToggleContainer: React.FunctionComponent<toggleProps> = (props) => {
@@ -44,22 +62,46 @@ const ToggleContainer: React.FunctionComponent<toggleProps> = (props) => {
}
};
+ const handleFilterChange = (event: React.MouseEvent<HTMLElement>, newView: string) => {
+ props.onToggleFilterButton();
+ };
+
const children = React.Children.toArray(props.children);
+ //hide filter if visible + table
+ //put current name into state, let container handle stuff itelf, register for togglestate, get right via set name
+
return (
<>
- <ToggleButtonGroup className={classes.toggleButton} size="medium" value={props.selectedValue} exclusive onChange={handleChange}>
- <ToggleButton aria-label="display-chart" key={1} value="chart">
- <Tooltip title="Chart">
- <BarChartIcon />
- </Tooltip>
- </ToggleButton>
- <ToggleButton aria-label="display-table" key={2} value="table">
- <Tooltip title="Table">
- <TableChartIcon />
- </Tooltip>
- </ToggleButton>
- </ToggleButtonGroup>
+ <div className={classes.toggleButtonContainer} >
+ <ToggleButtonGroup className={classes.subViewGroup} size="medium" value={props.selectedValue} exclusive onChange={handleChange}>
+ <ToggleButton aria-label="display-chart" key={1} value="chart">
+ <Tooltip title="Chart">
+ <BarChartIcon />
+ </Tooltip>
+ </ToggleButton>
+ <ToggleButton aria-label="display-table" key={2} value="table">
+ <Tooltip title="Table">
+ <TableChartIcon />
+ </Tooltip>
+ </ToggleButton>
+ </ToggleButtonGroup>
+
+ <ToggleButtonGroup className={classes.filterGroup} onChange={handleFilterChange} >
+ <ToggleButton aria-label="show-filter" selected={props.showFilter as boolean} disabled={props.selectedValue !== "chart"}>
+ <Tooltip title={props.showFilter ? 'Hide filter' : 'Show available filter'}>
+ <FilterListIcon />
+ </Tooltip>
+ </ToggleButton>
+ </ToggleButtonGroup>
+
+
+ </div>
+ {
+ props.selectedValue === "chart" &&
+ <ChartFilter filters={props.existingFilter} onFilterChanged={props.onFilterChanged} isVisible={props.showFilter} />
+
+ }
{props.selectedValue === "chart" ? children[0] : props.selectedValue === "table" && children[1]}
</>);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
index 6fe66d2b5..d89aca052 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
@@ -28,17 +28,22 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes';
import { createTransmissionPowerProperties, createTransmissionPowerActions } from '../handlers/transmissionPowerHandler';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
-import { SetSubViewAction } from '../actions/toggleActions';
+import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions';
import ToggleContainer from './toggleContainer';
const mapProps = (state: IApplicationStoreState) => ({
transmissionPowerProperties: createTransmissionPowerProperties(state),
- currentView: state.performanceHistory.subViews.transmissionPower,
+ currentView: state.performanceHistory.subViews.transmissionPower.subView,
+ isFilterVisible: state.performanceHistory.subViews.transmissionPower.isFilterVisible,
+ existingFilter: state.performanceHistory.transmissionPower.filter
});
const mapDisp = (dispatcher: IDispatcher) => ({
transmissionPowerActions: createTransmissionPowerActions(dispatcher.dispatch),
setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("transmissionPower", value)),
+ toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("transmissionPower", value)) },
+
+
});
type TransmissionPowerComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -52,6 +57,10 @@ const TransmissionPowerTable = MaterialTable as MaterialTableCtorType<Transmissi
*/
class TransmissionPowerComponent extends React.Component<TransmissionPowerComponentProps>{
+ onToggleFilterButton = () => {
+ this.props.toggleFilterButton(!this.props.isFilterVisible);
+ }
+
onChange = (value: "chart" | "table") => {
this.props.setSubView(value);
}
@@ -67,10 +76,7 @@ class TransmissionPowerComponent extends React.Component<TransmissionPowerCompon
{ property: "scannerId", title: "Scanner ID", type: ColumnType.text },
{ property: "timeStamp", title: "End Time", type: ColumnType.text },
{
- property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => {
- const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString();
- return <div >{suspectIntervalFlag} </div>
- }
+ property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean
}
];
@@ -80,9 +86,9 @@ class TransmissionPowerComponent extends React.Component<TransmissionPowerCompon
return (
<>
- <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ <ToggleContainer onChange={this.onChange} onToggleFilterButton={this.onToggleFilterButton} showFilter={this.props.isFilterVisible} existingFilter={this.props.transmissionPowerProperties.filter} onFilterChanged={this.props.transmissionPowerActions.onFilterChanged} selectedValue={this.props.currentView} >
{lineChart(chartPagedData)}
- <TransmissionPowerTable idProperty={"_id"} columns={transmissionColumns} {...properties} {...actions} />
+ <TransmissionPowerTable stickyHeader idProperty={"_id"} columns={transmissionColumns} {...properties} {...actions} />
</ToggleContainer>
</>
);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
index fd137fe37..4605efdb0 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
@@ -21,6 +21,8 @@ import {
AllAvailableLtpsLoadedAction,
LoadAllAvailableLtpsAction,
SetInitialLoadedAction,
+ NoLtpsFoundAction,
+ ResetLtpsAction,
} from '../actions/ltpAction';
import { LtpIds } from '../models/availableLtps';
@@ -29,12 +31,14 @@ export interface IAvailableLtpsState {
distinctLtps: LtpIds[];
busy: boolean;
loadedOnce: boolean;
+ error: string | undefined;
}
const ltpListStateInit: IAvailableLtpsState = {
distinctLtps: [],
busy: false,
- loadedOnce: false
+ loadedOnce: false,
+ error: undefined
};
export const availableLtpsActionHandler: IActionHandler<IAvailableLtpsState> = (state = ltpListStateInit, action) => {
@@ -51,8 +55,16 @@ export const availableLtpsActionHandler: IActionHandler<IAvailableLtpsState> = (
...state,
distinctLtps: action.availableLtps,
busy: false,
+ error: undefined,
loadedOnce: true
};
+ } else if (action.error) {
+ state = {
+ ...state,
+ busy: false,
+ loadedOnce: true,
+ error: action.error
+ }
}
} else if (action instanceof SetInitialLoadedAction) {
@@ -60,7 +72,25 @@ export const availableLtpsActionHandler: IActionHandler<IAvailableLtpsState> = (
...state,
loadedOnce: action.initialLoaded
};
- } else {
+ } else if (action instanceof NoLtpsFoundAction) {
+ state = {
+ ...state,
+ busy: false,
+ error: undefined,
+ loadedOnce: true,
+ distinctLtps: []
+ }
+ } else if (action instanceof ResetLtpsAction) {
+ state = {
+ ...state,
+ busy: false,
+ error: undefined,
+ loadedOnce: false,
+ distinctLtps: []
+ }
+ }
+
+ else {
state = {
...state,
busy: false
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
index e57f3860c..6b9081502 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
@@ -37,8 +37,8 @@ import { IAvailableLtpsState, availableLtpsActionHandler } from './availableLtps
import { PmDataInterval } from '../models/performanceDataType';
import { TimeChangeAction } from '../actions/timeChangeAction';
import { UpdateMountId } from '../actions/deviceListActions';
-import { SetSubViewAction, ResetAllSubViewsAction } from '../actions/toggleActions';
-import { SubTabType } from '../models/toggleDataType';
+import { SetSubViewAction, ResetAllSubViewsAction, SetFilterVisibility } from '../actions/toggleActions';
+import { SubTabType, currentViewType } from '../models/toggleDataType';
export interface IPerformanceHistoryStoreState {
nodeId: string;
@@ -81,24 +81,46 @@ const currentPMDataIntervalHandler: IActionHandler<PmDataInterval> = (state = Pm
return state;
}
+type filterableSubview = { subView: SubTabType, isFilterVisible: boolean };
+type toggleViewDataType = { currentSubView: currentViewType, performanceData: filterableSubview, receiveLevel: filterableSubview, transmissionPower: filterableSubview, adaptiveModulation: filterableSubview, temperatur: filterableSubview, SINR: filterableSubview, CPD: filterableSubview };
-type toggleViewDataType = { performanceDataSelection: SubTabType, receiveLevelDataSelection: SubTabType, transmissionPower: SubTabType, adaptiveModulation: SubTabType, temperatur: SubTabType, SINR: SubTabType, CPD: SubTabType };
-
-const toogleViewDataHandler: IActionHandler<toggleViewDataType> = (state = { performanceDataSelection: "chart", receiveLevelDataSelection: "chart", adaptiveModulation: "chart", transmissionPower: "chart", temperatur: "chart", SINR: "chart", CPD: "chart" }, action) => {
+const toogleViewDataHandler: IActionHandler<toggleViewDataType> = (state = { currentSubView: "performanceData", performanceData: { subView: "chart", isFilterVisible: true }, receiveLevel: { subView: "chart", isFilterVisible: true }, adaptiveModulation: { subView: "chart", isFilterVisible: true }, transmissionPower: { subView: "chart", isFilterVisible: true }, temperatur: { subView: "chart", isFilterVisible: true }, SINR: { subView: "chart", isFilterVisible: true }, CPD: { subView: "chart", isFilterVisible: true } }, action) => {
if (action instanceof SetSubViewAction) {
switch (action.currentView) {
- case "performanceData": state = { ...state, performanceDataSelection: action.selectedTab }; break;
- case "adaptiveModulation": state = { ...state, adaptiveModulation: action.selectedTab }; break;
- case "receiveLevel": state = { ...state, receiveLevelDataSelection: action.selectedTab }; break;
- case "transmissionPower": state = { ...state, transmissionPower: action.selectedTab }; break;
- case "Temp": state = { ...state, temperatur: action.selectedTab }; break;
- case "SINR": state = { ...state, SINR: action.selectedTab }; break;
- case "CPD": state = { ...state, CPD: action.selectedTab }; break;
+ case "performanceData": state = { ...state, performanceData: { ...state.performanceData, subView: action.selectedTab } }; break;
+ case "adaptiveModulation": state = { ...state, adaptiveModulation: { ...state.adaptiveModulation, subView: action.selectedTab } }; break;
+ case "receiveLevel": state = { ...state, receiveLevel: { ...state.receiveLevel, subView: action.selectedTab } }; break;
+ case "transmissionPower": state = { ...state, transmissionPower: { ...state.transmissionPower, subView: action.selectedTab } }; break;
+ case "Temp": state = { ...state, temperatur: { ...state.temperatur, subView: action.selectedTab } }; break;
+ case "SINR": state = { ...state, SINR: { ...state.SINR, subView: action.selectedTab } }; break;
+ case "CPD": state = { ...state, CPD: { ...state.CPD, subView: action.selectedTab } }; break;
+ }
+ }
+ else if (action instanceof SetFilterVisibility) {
+ switch (action.currentView) {
+ case "performanceData": state = {
+ ...state, performanceData: { ...state.performanceData, isFilterVisible: action.isVisible }
+ }; break;
+ case "adaptiveModulation": state = { ...state, adaptiveModulation: { ...state.performanceData, isFilterVisible: action.isVisible } }; break;
+ case "receiveLevel": state = { ...state, receiveLevel: { ...state.receiveLevel, isFilterVisible: action.isVisible } }; break;
+ case "transmissionPower": state = { ...state, transmissionPower: { ...state.transmissionPower, isFilterVisible: action.isVisible } }; break;
+ case "Temp": state = { ...state, temperatur: { ...state.temperatur, isFilterVisible: action.isVisible } }; break;
+ case "SINR": state = { ...state, SINR: { ...state.SINR, isFilterVisible: action.isVisible } }; break;
+ case "CPD": state = { ...state, CPD: { ...state.CPD, isFilterVisible: action.isVisible } }; break;
}
+
} else if (action instanceof ResetAllSubViewsAction) {
- state = { performanceDataSelection: "chart", adaptiveModulation: "chart", receiveLevelDataSelection: "chart", transmissionPower: "chart", temperatur: "chart", SINR: "chart", CPD: "chart" }
+ state = {
+ ...state, performanceData: { ...state.performanceData, subView: "chart" },
+ adaptiveModulation: { ...state.adaptiveModulation, subView: "chart" },
+ receiveLevel: { ...state.receiveLevel, subView: "chart" },
+ transmissionPower: { ...state.transmissionPower, subView: "chart" },
+ temperatur: { ...state.temperatur, subView: "chart" },
+ SINR: { ...state.SINR, subView: "chart" },
+ CPD: { ...state.CPD, subView: "chart" }
+ }
}
return state;
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
index 2b03d1c2e..685859850 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts
@@ -53,7 +53,7 @@ class PerformanceService {
}
const result = await requestRest<Result<string>>(path, { method: "POST", body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase)) });
- return result && result.output && result.output.data.map(ne => ({ key: ne })) || null;
+ return result && result.output && result.output.data && result.output.data.map(ne => ({ key: ne })) || null;
}
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
index 4984e80c3..4a1c654fb 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
@@ -39,7 +39,7 @@ import SignalToInterference from '../components/signalToInterference';
import CrossPolarDiscrimination from '../components/crossPolarDiscrimination';
import { loadAllDeviceListAsync } from '../actions/deviceListActions';
import { TimeChangeAction } from '../actions/timeChangeAction';
-import { loadDistinctLtpsbyNetworkElementAsync, SetInitialLoadedAction } from '../actions/ltpAction';
+import { loadDistinctLtpsbyNetworkElementAsync, ResetLtpsAction } from '../actions/ltpAction';
import { SetPanelAction } from '../actions/panelChangeActions';
import { createPerformanceDataPreActions, performanceDataReloadAction, createPerformanceDataActions } from '../handlers/performanceDataHandler';
import { createReceiveLevelPreActions, receiveLevelReloadAction, createReceiveLevelActions } from '../handlers/receiveLevelHandler';
@@ -69,7 +69,8 @@ const mapProps = (state: IApplicationStoreState) => ({
activePanel: state.performanceHistory.currentOpenPanel,
availableLtps: state.performanceHistory.ltps.distinctLtps,
networkElements: state.performanceHistory.networkElements.deviceList,
- initialLoaded: state.performanceHistory.ltps.loadedOnce
+ initialLoaded: state.performanceHistory.ltps.loadedOnce,
+ error: state.performanceHistory.ltps.error
});
const mapDispatcher = (dispatcher: IDispatcher) => ({
@@ -103,7 +104,7 @@ const mapDispatcher = (dispatcher: IDispatcher) => ({
changeNode: (nodeId: string) => dispatcher.dispatch((dispatch: Dispatch) => {
dispatch(new NavigateToApplication("performanceHistory", nodeId));
}),
- setInitialLoaded: (isLoaded: boolean) => dispatcher.dispatch((dispatch: Dispatch) => { dispatch(new SetInitialLoadedAction(isLoaded)); }),
+ resetLtps: () => dispatcher.dispatch((dispatch: Dispatch) => { dispatch(new ResetLtpsAction()); }),
resetSubViews: () => dispatcher.dispatch(new ResetAllSubViewsAction())
});
@@ -138,7 +139,7 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
constructor(props: PerformanceHistoryComponentProps) {
super(props);
this.state = {
- selectedNetworkElement: "-1",
+ selectedNetworkElement: props.nodeId !== "" ? props.nodeId : "-1",
selectedTimePeriod: "15min",
selectedLtp: "-1",
showNetworkElementsTable: true,
@@ -219,7 +220,7 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
if (nodeId === "") {
return (
<>
- <NetworkElementTable title={"Please select the network element!"} idProperty={"nodeId"} rows={this.props.networkElements} asynchronus
+ <NetworkElementTable stickyHeader title={"Please select the network element!"} idProperty={"nodeId"} rows={this.props.networkElements} asynchronus
onHandleClick={(event, rowData) => { this.handleNetworkElementSelect(rowData.nodeId) }} columns={
[{ property: "nodeId", title: "Node Name" }]
} />
@@ -232,7 +233,7 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
<>
{this.state.showLtps &&
- <LtpSelection selectedNE={this.state.selectedNetworkElement} selectedLtp={this.state.selectedLtp} selectedTimePeriod={this.state.selectedTimePeriod}
+ <LtpSelection error={this.props.error} selectedNE={this.state.selectedNetworkElement} selectedLtp={this.state.selectedLtp} selectedTimePeriod={this.state.selectedTimePeriod}
availableLtps={this.props.availableLtps} finishedLoading={this.props.initialLoaded} onChangeTimePeriod={this.handleTimePeriodChange}
onChangeLtp={this.handleLtpChange}
/>
@@ -293,6 +294,9 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
public componentDidMount() {
+ this.props.resetSubViews();
+ this.props.resetLtps();
+ this.props.setCurrentPanel(null);
this.props.getAllDevicesPMdata();
this.props.enableFilterPerformanceData.onToggleFilter();
this.props.enableFilterReceiveLevel.onToggleFilter();
@@ -301,8 +305,6 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
this.props.enableFilterAdaptiveModulation.onToggleFilter();
this.props.enableFilterSinr.onToggleFilter();
this.props.enableFilterCpd.onToggleFilter();
- this.props.setInitialLoaded(false);
- this.props.resetSubViews();
}
/**
@@ -377,8 +379,8 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
selectedLtp: "-1"
});
- this.props.setInitialLoaded(false);
this.props.resetSubViews();
+ this.props.resetLtps();
this.setState({ preFilter: {} });
this.props.changeNode(selectedNetworkElement);
this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, "-1", this.selectFirstLtp);
@@ -440,7 +442,6 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
showPanels: false,
selectedLtp: event.target.value
});
- this.props.setCurrentPanel(null);
} else if (event.target.value !== this.state.selectedLtp) {
this.setState({