summaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux
diff options
context:
space:
mode:
Diffstat (limited to 'sdnr/wt/odlux')
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts110
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx60
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx3
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx36
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx3
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts6
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts15
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx15
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx17
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx87
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx15
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx19
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx17
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx16
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx68
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx15
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts25
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts29
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts25
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx2
-rw-r--r--sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx286
-rw-r--r--sdnr/wt/odlux/framework/pom.xml2
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx4
-rw-r--r--sdnr/wt/odlux/framework/src/views/login.tsx29
-rw-r--r--sdnr/wt/odlux/package.json3
25 files changed, 680 insertions, 227 deletions
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
index 49c2b9be7..5322e1f6f 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
+++ b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
@@ -115,17 +115,26 @@ class YangLexer {
private _processIdentifier(): Token {
let endpos = this.pos + 1;
- while (endpos < this.buf.length &&
- this._isAlphanum(this.buf.charAt(endpos))) {
- endpos++;
+ while (endpos < this.buf.length && this._isAlphanum(this.buf.charAt(endpos))) {
+ ++endpos;
+ }
+
+ let name = 'IDENTIFIER'
+ if (this.buf.charAt(endpos) === ":") {
+ name = 'IDENTIFIERREF';
+ ++endpos;
+ while (endpos < this.buf.length && this._isAlphanum(this.buf.charAt(endpos))) {
+ ++endpos;
+ }
}
const tok = {
- name: 'IDENTIFIER',
+ name: name,
value: this.buf.substring(this.pos, endpos),
start: this.pos,
end: endpos
};
+
this.pos = endpos;
return tok;
}
@@ -214,7 +223,7 @@ class YangLexer {
current = stack.shift() || null;
}
this.pos++;
- } else if (this._isAlpha(char)) {
+ } else if (this._isAlpha(char) || char === "_") {
const key = this._processIdentifier().value;
this._skipNontokens();
let peekChar = this.buf.charAt(this.pos);
@@ -257,7 +266,7 @@ export class YangParser {
private _groupingsToResolve: (() => void)[] = [];
private _identityToResolve: (() => void)[] = [];
private _unionsToResolve: (() => void)[] = [];
-
+ private _modulesToResolve: (() => void)[] = [];
private _modules: { [name: string]: Module } = {};
private _views: ViewSpecification[] = [{
@@ -398,14 +407,16 @@ export class YangParser {
// create the root elements for this module
module.elements = currentView.elements;
- Object.keys(module.elements).forEach(key => {
- const viewElement = module.elements[key];
- if (!isViewElementObjectOrList(viewElement)) {
- throw new Error(`Module: [${module}]. Only List or Object allowed on root level.`);
- }
- const viewIdIndex = Number(viewElement.viewId);
- module.views[key] = this._views[viewIdIndex];
- this._views[0].elements[key] = module.elements[key];
+ this._modulesToResolve.push(() => {
+ Object.keys(module.elements).forEach(key => {
+ const viewElement = module.elements[key];
+ if (!isViewElementObjectOrList(viewElement)) {
+ throw new Error(`Module: [${module}]. Only List or Object allowed on root level.`);
+ }
+ const viewIdIndex = Number(viewElement.viewId);
+ module.views[key] = this._views[viewIdIndex];
+ this._views[0].elements[key] = module.elements[key];
+ });
});
return module;
}
@@ -482,6 +493,12 @@ export class YangParser {
console.warn(error.message);
}
});
+
+ this._modulesToResolve.forEach(cb => {
+ try { cb(); } catch (error) {
+ console.warn(error.message);
+ }
+ });
};
private _nextId = 1;
@@ -580,8 +597,16 @@ export class YangParser {
}
private extractSubViews(statement: Statement, parentId: number, module: Module, currentPath: string): [ViewSpecification, ViewSpecification[]] {
- const subViews: ViewSpecification[] = [];
+ // used for scoped definitions
+ const context: Module = {
+ ...module,
+ typedefs: {
+ ...module.typedefs
+ }
+ };
+
const currentId = this.nextId;
+ const subViews: ViewSpecification[] = [];
let elements: ViewElement[] = [];
const configValue = this.extractValue(statement, "config");
@@ -590,18 +615,26 @@ export class YangParser {
// extract conditions
const ifFeature = this.extractValue(statement, "if-feature");
const whenCondition = this.extractValue(statement, "when");
- if (whenCondition) console.warn("Found in [" + module.name + "]" + currentPath + " when: " + whenCondition);
+ if (whenCondition) console.warn("Found in [" + context.name + "]" + currentPath + " when: " + whenCondition);
+
+ // extract all scoped typedefs
+ this.extractTypeDefinitions(statement, context, currentPath);
+
+ // extract all scoped groupings
+ subViews.push(
+ ...this.extractGroupings(statement, parentId, context, currentPath)
+ );
// extract all container
const container = this.extractNodes(statement, "container");
if (container && container.length > 0) {
subViews.push(...container.reduce<ViewSpecification[]>((acc, cur) => {
if (!cur.arg) {
- throw new Error(`Module: [${module.name}]${currentPath}. Found container without name.`);
+ throw new Error(`Module: [${context.name}]${currentPath}. Found container without name.`);
}
- const [currentView, subViews] = this.extractSubViews(cur, currentId, module, `${currentPath}/${module.name}:${cur.arg}`);
+ const [currentView, subViews] = this.extractSubViews(cur, currentId, context, `${currentPath}/${context.name}:${cur.arg}`);
elements.push({
- id: parentId === 0 ? `${module.name}:${cur.arg}` : cur.arg,
+ id: parentId === 0 ? `${context.name}:${cur.arg}` : cur.arg,
label: cur.arg,
uiType: "object",
viewId: currentView.id,
@@ -618,15 +651,15 @@ export class YangParser {
if (lists && lists.length > 0) {
subViews.push(...lists.reduce<ViewSpecification[]>((acc, cur) => {
if (!cur.arg) {
- throw new Error(`Module: [${module.name}]${currentPath}. Found list without name.`);
+ throw new Error(`Module: [${context.name}]${currentPath}. Found list without name.`);
}
const key = this.extractValue(cur, "key") || undefined;
if (config && !key) {
- throw new Error(`Module: [${module.name}]${currentPath}. Found configurable list without key.`);
+ throw new Error(`Module: [${context.name}]${currentPath}. Found configurable list without key.`);
}
- const [currentView, subViews] = this.extractSubViews(cur, currentId, module, `${currentPath}/${module.name}:${cur.arg}`);
+ const [currentView, subViews] = this.extractSubViews(cur, currentId, context, `${currentPath}/${context.name}:${cur.arg}`);
elements.push({
- id: parentId === 0 ? `${module.name}:${cur.arg}` : cur.arg,
+ id: parentId === 0 ? `${context.name}:${cur.arg}` : cur.arg,
label: cur.arg,
isList: true,
uiType: "object",
@@ -644,7 +677,7 @@ export class YangParser {
const leafLists = this.extractNodes(statement, "leaf-list");
if (leafLists && leafLists.length > 0) {
elements.push(...leafLists.reduce<ViewElement[]>((acc, cur) => {
- const element = this.getViewElement(cur, module, parentId, currentPath, true);
+ const element = this.getViewElement(cur, context, parentId, currentPath, true);
element && acc.push(element);
return acc;
}, []));
@@ -655,7 +688,7 @@ export class YangParser {
const leafs = this.extractNodes(statement, "leaf");
if (leafs && leafs.length > 0) {
elements.push(...leafs.reduce<ViewElement[]>((acc, cur) => {
- const element = this.getViewElement(cur, module, parentId, currentPath, false);
+ const element = this.getViewElement(cur, context, parentId, currentPath, false);
element && acc.push(element);
return acc;
}, []));
@@ -666,7 +699,7 @@ export class YangParser {
if (choiceStms && choiceStms.length > 0) {
elements.push(...choiceStms.reduce<ViewElementChoise[]>((accChoise, curChoise) => {
if (!curChoise.arg) {
- throw new Error(`Module: [${module.name}]${currentPath}. Found choise without name.`);
+ throw new Error(`Module: [${context.name}]${currentPath}. Found choise without name.`);
}
// extract all cases like containers
const cases: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } }[] = [];
@@ -674,14 +707,14 @@ export class YangParser {
if (caseStms && caseStms.length > 0) {
cases.push(...caseStms.reduce((accCase, curCase) => {
if (!curCase.arg) {
- throw new Error(`Module: [${module.name}]${currentPath}/${curChoise.arg}. Found case without name.`);
+ throw new Error(`Module: [${context.name}]${currentPath}/${curChoise.arg}. Found case without name.`);
}
const description = this.extractValue(curCase, "description") || undefined;
- const [caseView, caseSubViews] = this.extractSubViews(curCase, parentId, module, `${currentPath}/${module.name}:${curChoise.arg}`);
+ const [caseView, caseSubViews] = this.extractSubViews(curCase, parentId, context, `${currentPath}/${context.name}:${curChoise.arg}`);
subViews.push(caseView, ...caseSubViews);
const caseDef: { id: string, label: string, description?: string, elements: { [name: string]: ViewElement } } = {
- id: parentId === 0 ? `${module.name}:${curCase.arg}` : curCase.arg,
+ id: parentId === 0 ? `${context.name}:${curCase.arg}` : curCase.arg,
label: curCase.arg,
description: description,
elements: caseView.elements
@@ -692,7 +725,7 @@ export class YangParser {
}
// extract all simple cases (one case per leaf, container, etc.)
- const [choiseView, choiseSubViews] = this.extractSubViews(curChoise, parentId, module, `${currentPath}/${module.name}:${curChoise.arg}`);
+ const [choiseView, choiseSubViews] = this.extractSubViews(curChoise, parentId, context, `${currentPath}/${context.name}:${curChoise.arg}`);
subViews.push(choiseView, ...choiseSubViews);
cases.push(...Object.keys(choiseView.elements).reduce((accElm, curElm) => {
const elm = choiseView.elements[curElm];
@@ -714,7 +747,7 @@ export class YangParser {
const element: ViewElementChoise = {
uiType: "choise",
- id: parentId === 0 ? `${module.name}:${curChoise.arg}` : curChoise.arg,
+ id: parentId === 0 ? `${context.name}:${curChoise.arg}` : curChoise.arg,
label: curChoise.arg,
config: config,
mandatory: mandatory,
@@ -736,7 +769,7 @@ export class YangParser {
}
if (!statement.arg) {
- throw new Error(`Module: [${module.name}]. Found statement without name.`);
+ throw new Error(`Module: [${context.name}]. Found statement without name.`);
}
const viewSpec: ViewSpecification = {
@@ -772,13 +805,13 @@ export class YangParser {
for (let i = 0; i < usesRefs.length; ++i) {
const groupingName = usesRefs[i].arg;
if (!groupingName) {
- throw new Error(`Module: [${module.name}]. Found an uses statement without a grouping name.`);
+ throw new Error(`Module: [${context.name}]. Found an uses statement without a grouping name.`);
}
- viewSpec.uses.push(this.resolveReferencePath(groupingName, module));
+ viewSpec.uses.push(this.resolveReferencePath(groupingName, context));
this._groupingsToResolve.push(() => {
- const groupingViewSpec = this.resolveGrouping(groupingName, module);
+ const groupingViewSpec = this.resolveGrouping(groupingName, context);
if (groupingViewSpec) {
Object.keys(groupingViewSpec.elements).forEach(key => {
const elm = groupingViewSpec.elements[key];
@@ -1140,6 +1173,13 @@ export class YangParser {
uiType: "binary",
length: extractRange(0, +18446744073709551615, "length"),
};
+ } else if (type === "instance-identifier") {
+ // https://tools.ietf.org/html/rfc7950#page-168
+ return {
+ ...element,
+ uiType: "string",
+ length: extractRange(0, +18446744073709551615, "length"),
+ };
} else {
// not a build in type, have to resolve type
let typeRef = this.resolveType(type, module);
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
index 0370df7cb..45003e741 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
@@ -24,6 +24,7 @@ import LinkOffIcon from '@material-ui/icons/LinkOff';
import RemoveIcon from '@material-ui/icons/RemoveCircleOutline';
import EditIcon from '@material-ui/icons/Edit';
import Info from '@material-ui/icons/Info';
+import ComputerIcon from '@material-ui/icons/Computer';
import { MaterialTable, ColumnType, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
@@ -98,11 +99,42 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
};
}
+ getContextMenu(rowData: NetworkElementConnection): JSX.Element[] {
+
+
+
+ const { configuration, fault, inventory } = this.props.applicationState as any;
+ let buttonArray = [
+ <MenuItem aria-label={"mount-button"} onClick={event => this.onOpenMountdNetworkElementsDialog(event, rowData)} ><LinkIcon /><Typography>Mount</Typography></MenuItem>,
+ <MenuItem aria-label={"unmount-button"} onClick={event => this.onOpenUnmountdNetworkElementsDialog(event, rowData)}><LinkOffIcon /><Typography>Unmount</Typography></MenuItem>,
+ <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>,
+ <Divider />,
+ <MenuItem aria-label={"inventory-button"} onClick={event => this.props.navigateToApplication("inventory", rowData.nodeId)}><Typography>Inventory</Typography></MenuItem>,
+ <Divider />,
+ <MenuItem aria-label={"fault-button"} onClick={event => this.props.navigateToApplication("fault", rowData.nodeId)} ><Typography>Fault</Typography></MenuItem>,
+ <MenuItem aria-label={"configure-button"} onClick={event => this.props.navigateToApplication("configuration", rowData.nodeId)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected" || !configuration}><Typography>Configure</Typography></MenuItem>,
+ <MenuItem onClick={event => this.props.navigateToApplication("accounting", rowData.nodeId)} disabled={true}><Typography>Accounting</Typography></MenuItem>,
+ <MenuItem aria-label={"performance-button"} onClick={event => this.props.navigateToApplication("performanceHistory", rowData.nodeId)}><Typography>Performance</Typography></MenuItem>,
+ <MenuItem onClick={event => this.props.navigateToApplication("security", rowData.nodeId)} disabled={true} ><Typography>Security</Typography></MenuItem>,
+ ];
+
+ if (rowData.webUri) {
+ // add an icon for gui cuttrough, if weburi is available
+ return [<MenuItem aria-label={"web-client-button"} onClick={event => window.open(rowData.webUri, "_blank")} ><ComputerIcon /><Typography>Web Client</Typography></MenuItem>].concat(buttonArray)
+ } else {
+ return buttonArray;
+ }
+ }
+
// private navigationCreator
render(): JSX.Element {
const { classes } = this.props;
- const { framework, connect, configuration, fault, help, inventory, maintenance, mediator } = this.props.applicationState as any;
const { networkElementToEdit } = this.state;
const addRequireNetworkElementAction = {
icon: AddIcon, tooltip: 'Add', onClick: () => {
@@ -112,7 +144,7 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
});
}
};
- let counter = 0;
+
return (
<>
<NetworkElementTable stickyHeader tableId="network-element-table" customActionButtons={[addRequireNetworkElementAction]} columns={[
@@ -124,24 +156,8 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
{ property: "coreModelCapability", title: "Core Model", type: ColumnType.text },
{ property: "deviceType", title: "Type", type: ColumnType.text },
]} idProperty="id" {...this.props.networkElementsActions} {...this.props.networkElementsProperties} asynchronus createContextMenu={rowData => {
- return [
- <MenuItem onClick={event => this.onOpenMountdNetworkElementsDialog(event, rowData)} ><LinkIcon /><Typography>Mount</Typography></MenuItem>,
- <MenuItem onClick={event => this.onOpenUnmountdNetworkElementsDialog(event, rowData)}><LinkOffIcon /><Typography>Unmount</Typography></MenuItem>,
- <Divider />,
- <MenuItem onClick={event => this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected"} ><Info /><Typography>Info</Typography></MenuItem>,
- <MenuItem onClick={event => this.onOpenEditNetworkElementDialog(event, rowData)}><EditIcon /><Typography>Edit</Typography></MenuItem>,
- !rowData.isRequired
- ? <MenuItem onClick={event => this.onOpenAddNetworkElementDialog(event, rowData)} ><AddIcon /><Typography>Add</Typography></MenuItem>
- : <MenuItem onClick={event => this.onOpenRemoveNetworkElementDialog(event, rowData)} ><RemoveIcon /><Typography>Remove</Typography></MenuItem>,
- <Divider />,
- <MenuItem onClick={event => this.navigateToApplicationHandlerCreator("inventory", rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected" || !inventory}><Typography>Inventory</Typography></MenuItem>,
- <Divider />,
- <MenuItem onClick={event => this.navigateToApplicationHandlerCreator("fault", rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected" || !fault}><Typography>Fault</Typography></MenuItem>,
- <MenuItem onClick={event => this.navigateToApplicationHandlerCreator("configuration", rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected" || !configuration}><Typography>Configure</Typography></MenuItem>,
- <MenuItem onClick={event => this.navigateToApplicationHandlerCreator("accounting", rowData)} disabled={true}><Typography>Accounting</Typography></MenuItem>,
- <MenuItem onClick={event => this.navigateToApplicationHandlerCreator("performanceHistory", rowData)} disabled={true}><Typography>Performance</Typography></MenuItem>,
- <MenuItem onClick={event => this.navigateToApplicationHandlerCreator("security", rowData)} disabled={true} ><Typography>Security</Typography></MenuItem>,
- ];
+
+ return this.getContextMenu(rowData);
}} >
</NetworkElementTable>
<EditNetworkElementDialog
@@ -224,10 +240,6 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
networkElementToEdit: emptyRequireNetworkElement,
});
}
-
- private navigateToApplicationHandlerCreator = (applicationName: string, element: NetworkElementConnection) => (event: React.MouseEvent<HTMLElement>) => {
- this.props.navigateToApplication(applicationName, element.nodeId);
- }
}
export const NetworkElementsList = withStyles(styles)(connect(mapProps, mapDispatch)(NetworkElementsListComponent));
diff --git a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
index 5adc9d49c..cbcfd84d6 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
@@ -87,8 +87,7 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen
}
private onHandleTabChange = (event: React.ChangeEvent<{}>, newValue: PanelId) => {
- this.props.switchActivePanel(newValue);
- //this.onToggleTabs(newValue);
+ this.onToggleTabs(newValue);
}
private onToggleTabs = (panelId: PanelId) => {
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx
index e0cd51493..5ffd98799 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/components/editMaintenenceEntryDialog.tsx
@@ -33,7 +33,7 @@ import {
} from '../actions/maintenenceActions';
import { MaintenenceEntry } from '../models/maintenenceEntryType';
-import { FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
+import { FormControl, InputLabel, Select, MenuItem, Typography } from '@material-ui/core';
export enum EditMaintenenceEntryDialogMode {
None = "none",
@@ -101,14 +101,15 @@ type EditMaintenenceEntryDIalogComponentProps = Connect<undefined, typeof mapDis
onClose: () => void;
};
-type EditMaintenenceEntryDIalogComponentState = MaintenenceEntry;
+type EditMaintenenceEntryDIalogComponentState = MaintenenceEntry & { isErrorVisible: boolean };
class EditMaintenenceEntryDIalogComponent extends React.Component<EditMaintenenceEntryDIalogComponentProps, EditMaintenenceEntryDIalogComponentState> {
- constructor (props: EditMaintenenceEntryDIalogComponentProps) {
+ constructor(props: EditMaintenenceEntryDIalogComponentProps) {
super(props);
this.state = {
- ...this.props.initialMaintenenceEntry
+ ...this.props.initialMaintenenceEntry,
+ isErrorVisible: false
};
}
@@ -122,11 +123,12 @@ class EditMaintenenceEntryDIalogComponent extends React.Component<EditMaintenenc
{setting.dialogDescription}
</DialogContentText>
<TextField disabled={!setting.enableMountIdEditor} spellCheck={false} autoFocus margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.nodeId} onChange={(event) => { this.setState({ nodeId: event.target.value }); }} />
+ {this.state.isErrorVisible && <Typography variant="body1" color="error" >Name must not be empty.</Typography>}
<TextField disabled={!setting.enableTimeEditor} spellCheck={false} autoFocus margin="dense" id="start" label="Start (Local DateTime)" type="datetime-local" fullWidth value={this.state.start} onChange={(event) => { this.setState({ start: event.target.value }); }} />
<TextField disabled={!setting.enableTimeEditor} spellCheck={false} autoFocus margin="dense" id="end" label="End (Local DateTime)" type="datetime-local" fullWidth value={this.state.end} onChange={(event) => { this.setState({ end: event.target.value }); }} />
<FormControl fullWidth disabled={!setting.enableTimeEditor}>
<InputLabel htmlFor="active">Active</InputLabel>
- <Select value={ this.state.active || false } onChange={(event) => {
+ <Select value={this.state.active || false} onChange={(event) => {
this.setState({ active: event.target.value as any as boolean });
}} inputProps={{ name: 'active', id: 'active' }} fullWidth >
<MenuItem value={true as any as string}>active</MenuItem>
@@ -136,14 +138,21 @@ class EditMaintenenceEntryDIalogComponent extends React.Component<EditMaintenenc
</DialogContent>
<DialogActions>
<Button onClick={(event) => {
- this.onApply({
- _id: this.state._id || this.state.nodeId,
- nodeId: this.state.nodeId,
- description: this.state.description,
- start: this.state.start,
- end: this.state.end,
- active: this.state.active
- });
+
+ if (this.props.mode === EditMaintenenceEntryDialogMode.AddMaintenenceEntry && this.state.nodeId.trim().length === 0) {
+ this.setState({ isErrorVisible: true });
+ } else {
+ this.onApply({
+ _id: this.state._id || this.state.nodeId,
+ nodeId: this.state.nodeId,
+ description: this.state.description,
+ start: this.state.start,
+ end: this.state.end,
+ active: this.state.active
+ });
+ this.setState({ isErrorVisible: false });
+ }
+
event.preventDefault();
event.stopPropagation();
}} > {setting.applyButtonText} </Button>
@@ -151,6 +160,7 @@ class EditMaintenenceEntryDIalogComponent extends React.Component<EditMaintenenc
this.onCancel();
event.preventDefault();
event.stopPropagation();
+ this.setState({ isErrorVisible: false });
}} color="secondary"> {setting.cancelButtonText} </Button>
</DialogActions>
</Dialog>
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx
index 882a6b37e..d520db466 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx
@@ -161,7 +161,7 @@ class EditMediatorServerDialogComponent extends React.Component<EditMediatorServ
<Button onClick={(event) => {
if (this.areFieldsValid()) {
- this.setState({ errorMessage: [] })
+ this.setState({ errorMessage: [] });
this.onApply({
id: this.state.id,
name: this.state.name,
@@ -177,6 +177,7 @@ class EditMediatorServerDialogComponent extends React.Component<EditMediatorServ
}} > {setting.applyButtonText} </Button>
<Button onClick={(event) => {
this.onCancel();
+ this.setState({ errorMessage: [] });
event.preventDefault();
event.stopPropagation();
}} color="secondary"> {setting.cancelButtonText} </Button>
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
index 2741d889a..375617593 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/ltpAction.ts
@@ -44,6 +44,12 @@ export class AllAvailableLtpsLoadedAction extends BaseAction {
}
}
+export class SetInitialLoadedAction extends BaseAction {
+ constructor(public initialLoaded: boolean) {
+ super();
+ }
+}
+
/**
* Represents an asynchronous thunk action to load available distinctLtps by networkElement from the database and set the returned first Ltp as default.
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts
new file mode 100644
index 000000000..1f53a5806
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts
@@ -0,0 +1,15 @@
+import { Action } from "../../../../framework/src/flux/action";
+import { currentViewType } from "../models/toggleDataType";
+
+
+export class SetSubViewAction extends Action {
+ constructor(public currentView: currentViewType, public selectedTab: "chart" | "table") {
+ super();
+ }
+}
+
+export class ResetAllSubViewsAction extends Action {
+ constructor() {
+ 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 09d3accd4..c62698630 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx
@@ -28,13 +28,18 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes';
import { createAdaptiveModulationProperties, createAdaptiveModulationActions } from '../handlers/adaptiveModulationHandler';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
+import ToggleContainer from './toggleContainer';
+import { SetSubViewAction } from '../actions/toggleActions';
const mapProps = (state: IApplicationStoreState) => ({
adaptiveModulationProperties: createAdaptiveModulationProperties(state),
+ currentView: state.performanceHistory.subViews.adaptiveModulation,
+
});
const mapDisp = (dispatcher: IDispatcher) => ({
adaptiveModulationActions: createAdaptiveModulationActions(dispatcher.dispatch),
+ setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("adaptiveModulation", value)),
});
type AdaptiveModulationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -47,6 +52,10 @@ 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>{
+ onChange = (value: "chart" | "table") => {
+ this.props.setSubView(value);
+ }
+
render(): JSX.Element {
const properties = this.props.adaptiveModulationProperties;
const actions = this.props.adaptiveModulationActions;
@@ -69,8 +78,10 @@ class AdaptiveModulationComponent extends React.Component<AdaptiveModulationComp
return (
<>
- {lineChart(chartPagedData)}
- <AdaptiveModulationTable idProperty={"_id"} columns={adaptiveModulationColumns} {...properties} {...actions} />
+ <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ {lineChart(chartPagedData)}
+ <AdaptiveModulationTable idProperty={"_id"} columns={adaptiveModulationColumns} {...properties} {...actions} />
+ </ToggleContainer>
</>
);
};
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
index 267e00bbe..7489757f5 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx
@@ -28,13 +28,19 @@ 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 ToggleContainer from './toggleContainer';
+
const mapProps = (state: IApplicationStoreState) => ({
crossPolarDiscriminationProperties: createCrossPolarDiscriminationProperties(state),
+ currentView: state.performanceHistory.subViews.CPD,
+
});
const mapDisp = (dispatcher: IDispatcher) => ({
crossPolarDiscriminationActions: createCrossPolarDiscriminationActions(dispatcher.dispatch),
+ setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("CPD", value)),
});
type CrossPolarDiscriminationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -47,6 +53,11 @@ const CrossPolarDiscriminationTable = MaterialTable as MaterialTableCtorType<Cro
* The Component which gets the crossPolarDiscrimination data from the database based on the selected time period.
*/
class CrossPolarDiscriminationComponent extends React.Component<CrossPolarDiscriminationComponentProps>{
+
+ onChange = (value: "chart" | "table") => {
+ this.props.setSubView(value);
+ }
+
render(): JSX.Element {
const properties = this.props.crossPolarDiscriminationProperties;
const actions = this.props.crossPolarDiscriminationActions;
@@ -70,8 +81,10 @@ class CrossPolarDiscriminationComponent extends React.Component<CrossPolarDiscri
});
return (
<>
- {lineChart(chartPagedData)}
- <CrossPolarDiscriminationTable idProperty={"_id"} columns={cpdColumns} {...properties} {...actions} />
+ <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ {lineChart(chartPagedData)}
+ <CrossPolarDiscriminationTable 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
new file mode 100644
index 000000000..8327ec4ed
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx
@@ -0,0 +1,87 @@
+/**
+ * ============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 * as React from 'react';
+import { MenuItem, Select, FormControl } from '@material-ui/core';
+import { makeStyles } from '@material-ui/core/styles';
+import { LtpIds } from 'models/availableLtps';
+import { Loader } from '../../../../framework/src/components/material-ui';
+
+
+const useStyles = makeStyles(theme => ({
+ display: {
+ display: "inline-block"
+ },
+ selectDropdown: {
+ borderRadius: 1,
+ position: "relative",
+ backgroundColor: theme.palette.background.paper,
+ border: "1px solid #ced4da",
+ fontSize: 16,
+ width: "auto",
+ padding: "5px 26px 5px 12px",
+ transition: theme.transitions.create(["border-color", "box-shadow"]),
+ },
+ center: {
+ "flex": "1",
+ "height": "100%",
+ "display": "flex",
+ "alignItems": "center",
+ "justifyContent": "center",
+ }
+}));
+
+type LtpSelectionProps = { selectedNE: 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();
+ return (
+ <>
+ <h3>Selected Network Element: {props.selectedNE} </h3>
+ <FormControl className={classes.display}>
+ <span>
+ Select LTP
+ </span>
+ <Select className={classes.selectDropdown} value={props.selectedLtp} onChange={props.onChangeLtp} >
+ <MenuItem value={"-1"}><em>--Select--</em></MenuItem>
+ {props.availableLtps.map(ltp =>
+ (<MenuItem value={ltp.key} key={ltp.key}>{ltp.key}</MenuItem>))}
+ </Select>
+ <span> Time-Period </span>
+ <Select className={classes.selectDropdown} value={props.selectedTimePeriod} onChange={props.onChangeTimePeriod} >
+ <MenuItem value={"15min"}>15min</MenuItem>
+ <MenuItem value={"24hours"}>24hours</MenuItem>
+ </Select>
+ </FormControl>
+ {
+ !props.finishedLoading &&
+ <div className={classes.center}>
+ <Loader />
+ <h3>Collecting Data ...</h3>
+ </div>
+ }
+ {
+ props.selectedLtp === "-1" && props.finishedLoading &&
+ <div className={classes.center}>
+ <h3>Please select a LTP</h3>
+ </div>
+ }
+ </>)
+}
+
+export default LtpSelection; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
index c58c49c9e..d0caa6fd6 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx
@@ -27,13 +27,17 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes';
import { createPerformanceDataProperties, createPerformanceDataActions } from '../handlers/performanceDataHandler';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
+import ToggleContainer from './toggleContainer';
+import { SetSubViewAction } from '../actions/toggleActions';
const mapProps = (state: IApplicationStoreState) => ({
performanceDataProperties: createPerformanceDataProperties(state),
+ currentView: state.performanceHistory.subViews.performanceDataSelection,
});
const mapDisp = (dispatcher: IDispatcher) => ({
performanceDataActions: createPerformanceDataActions(dispatcher.dispatch),
+ setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("performanceData", value)),
});
type PerformanceDataComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -46,6 +50,11 @@ const PerformanceDataTable = MaterialTable as MaterialTableCtorType<PerformanceD
* The Component which gets the performance data from the database based on the selected time period.
*/
class PerformanceDataComponent extends React.Component<PerformanceDataComponentProps>{
+
+ onChange = (value: "chart" | "table") => {
+ this.props.setSubView(value);
+ }
+
render(): JSX.Element {
const properties = this.props.performanceDataProperties;
const actions = this.props.performanceDataActions;
@@ -68,8 +77,10 @@ class PerformanceDataComponent extends React.Component<PerformanceDataComponentP
});
return (
<>
- {lineChart(chartPagedData)}
- <PerformanceDataTable idProperty={"_id"} columns={performanceColumns} {...properties} {...actions} />
+ <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ {lineChart(chartPagedData)}
+ <PerformanceDataTable 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 55bc39860..4b0a835d4 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx
@@ -23,18 +23,24 @@ import { MaterialTable, ColumnType, ColumnModel, MaterialTableCtorType } from '.
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { ReceiveLevelDataType,ReceiveLevelDatabaseDataType } from '../models/receiveLevelDataType';
+import { ReceiveLevelDataType, ReceiveLevelDatabaseDataType } from '../models/receiveLevelDataType';
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 ToggleContainer from './toggleContainer';
const mapProps = (state: IApplicationStoreState) => ({
receiveLevelProperties: createReceiveLevelProperties(state),
+ currentView: state.performanceHistory.subViews.receiveLevelDataSelection,
+
});
const mapDisp = (dispatcher: IDispatcher) => ({
receiveLevelActions: createReceiveLevelActions(dispatcher.dispatch),
+ setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("receiveLevel", value)),
+
});
type ReceiveLevelComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -47,6 +53,11 @@ const ReceiveLevelTable = MaterialTable as MaterialTableCtorType<ReceiveLevelDat
* The Component which gets the receiveLevel data from the database based on the selected time period.
*/
class ReceiveLevelComponent extends React.Component<ReceiveLevelComponentProps>{
+
+ onChange = (value: "chart" | "table") => {
+ this.props.setSubView(value);
+ }
+
render(): JSX.Element {
const properties = this.props.receiveLevelProperties;
const actions = this.props.receiveLevelActions;
@@ -70,8 +81,10 @@ class ReceiveLevelComponent extends React.Component<ReceiveLevelComponentProps>{
return (
<>
- {lineChart(chartPagedData)}
- <ReceiveLevelTable idProperty={"_id"} columns={receiveLevelColumns} {...properties} {...actions} />
+ <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ {lineChart(chartPagedData)}
+ <ReceiveLevelTable 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 42aa007a9..ba480d57d 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx
@@ -28,13 +28,17 @@ 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 ToggleContainer from './toggleContainer';
const mapProps = (state: IApplicationStoreState) => ({
signalToInterferenceProperties: createSignalToInterferenceProperties(state),
+ currentView: state.performanceHistory.subViews.SINR,
});
const mapDisp = (dispatcher: IDispatcher) => ({
signalToInterferenceActions: createSignalToInterferenceActions(dispatcher.dispatch),
+ setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("SINR", value)),
});
type SignalToInterferenceComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -47,6 +51,11 @@ const SignalToInterferenceTable = MaterialTable as MaterialTableCtorType<SignalT
* The Component which gets the signal to interference data from the database based on the selected time period.
*/
class SignalToInterferenceComponent extends React.Component<SignalToInterferenceComponentProps>{
+
+ onChange = (value: "chart" | "table") => {
+ this.props.setSubView(value);
+ }
+
render(): JSX.Element {
const properties = this.props.signalToInterferenceProperties;
const actions = this.props.signalToInterferenceActions;
@@ -70,9 +79,11 @@ class SignalToInterferenceComponent extends React.Component<SignalToInterference
});
return (
<>
- {lineChart(chartPagedData)}
- <SignalToInterferenceTable idProperty={"_id"} columns={sinrColumns} {...properties} {...actions}
- />
+ <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ {lineChart(chartPagedData)}
+ <SignalToInterferenceTable 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 256911c2d..28f75d84c 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx
@@ -28,13 +28,17 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes';
import { createTemperatureProperties, createTemperatureActions } from '../handlers/temperatureHandler';
import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils';
import { addColumnLabels } from '../utils/tableUtils';
+import ToggleContainer from './toggleContainer';
+import { SetSubViewAction } from '../actions/toggleActions';
const mapProps = (state: IApplicationStoreState) => ({
temperatureProperties: createTemperatureProperties(state),
+ currentView: state.performanceHistory.subViews.temperatur,
});
const mapDisp = (dispatcher: IDispatcher) => ({
temperatureActions: createTemperatureActions(dispatcher.dispatch),
+ setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("Temp", value)),
});
type TemperatureComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -47,6 +51,11 @@ const TemperatureTable = MaterialTable as MaterialTableCtorType<TemperatureDataT
* The Component which gets the temperature data from the database based on the selected time period.
*/
class TemperatureComponent extends React.Component<TemperatureComponentProps>{
+
+ onChange = (value: "chart" | "table") => {
+ this.props.setSubView(value);
+ }
+
render(): JSX.Element {
const properties = this.props.temperatureProperties;
const actions = this.props.temperatureActions;
@@ -69,8 +78,11 @@ class TemperatureComponent extends React.Component<TemperatureComponentProps>{
});
return (
<>
- {lineChart(chartPagedData)}
- <TemperatureTable idProperty={"_id"} columns={temperatureColumns} {...properties} {...actions} />
+
+ <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ {lineChart(chartPagedData)}
+ <TemperatureTable 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
new file mode 100644
index 000000000..97a2006f7
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx
@@ -0,0 +1,68 @@
+/**
+ * ============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 * as React from 'react';
+import ToggleButton from '@material-ui/lab/ToggleButton';
+import ToggleButtonGroup from '@material-ui/lab/ToggleButtonGroup';
+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';
+
+const styles = makeStyles({
+ toggleButton: {
+ alignItems: "center",
+ justifyContent: "center",
+ padding: "10px",
+ }
+});
+
+type toggleProps = { selectedValue: string, onChange(value: string): void };
+
+const ToggleContainer: React.FunctionComponent<toggleProps> = (props) => {
+
+ const classes = styles();
+
+ const handleChange = (event: React.MouseEvent<HTMLElement>, newView: string) => {
+ if (newView !== null) {
+ props.onChange(newView)
+ }
+ };
+
+ const children = React.Children.toArray(props.children);
+
+ 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>
+ {props.selectedValue === "chart" ? children[0] : props.selectedValue === "table" && children[1]}
+ </>);
+
+}
+
+export default ToggleContainer; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
index 635cbf103..6fe66d2b5 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx
@@ -28,13 +28,17 @@ 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 ToggleContainer from './toggleContainer';
const mapProps = (state: IApplicationStoreState) => ({
transmissionPowerProperties: createTransmissionPowerProperties(state),
+ currentView: state.performanceHistory.subViews.transmissionPower,
});
const mapDisp = (dispatcher: IDispatcher) => ({
transmissionPowerActions: createTransmissionPowerActions(dispatcher.dispatch),
+ setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("transmissionPower", value)),
});
type TransmissionPowerComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp> & {
@@ -47,6 +51,11 @@ const TransmissionPowerTable = MaterialTable as MaterialTableCtorType<Transmissi
* The Component which gets the transmission power data from the database based on the selected time period.
*/
class TransmissionPowerComponent extends React.Component<TransmissionPowerComponentProps>{
+
+ onChange = (value: "chart" | "table") => {
+ this.props.setSubView(value);
+ }
+
render(): JSX.Element {
const properties = this.props.transmissionPowerProperties
const actions = this.props.transmissionPowerActions
@@ -71,8 +80,10 @@ class TransmissionPowerComponent extends React.Component<TransmissionPowerCompon
return (
<>
- {lineChart(chartPagedData)}
- <TransmissionPowerTable idProperty={"_id"} columns={transmissionColumns} {...properties} {...actions} />
+ <ToggleContainer selectedValue={this.props.currentView} onChange={this.onChange}>
+ {lineChart(chartPagedData)}
+ <TransmissionPowerTable 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 b3b284b42..fd137fe37 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts
@@ -20,6 +20,7 @@ import { IActionHandler } from '../../../../framework/src/flux/action';
import {
AllAvailableLtpsLoadedAction,
LoadAllAvailableLtpsAction,
+ SetInitialLoadedAction,
} from '../actions/ltpAction';
import { LtpIds } from '../models/availableLtps';
@@ -27,11 +28,13 @@ import { LtpIds } from '../models/availableLtps';
export interface IAvailableLtpsState {
distinctLtps: LtpIds[];
busy: boolean;
+ loadedOnce: boolean;
}
const ltpListStateInit: IAvailableLtpsState = {
distinctLtps: [],
- busy: false
+ busy: false,
+ loadedOnce: false
};
export const availableLtpsActionHandler: IActionHandler<IAvailableLtpsState> = (state = ltpListStateInit, action) => {
@@ -47,14 +50,22 @@ export const availableLtpsActionHandler: IActionHandler<IAvailableLtpsState> = (
state = {
...state,
distinctLtps: action.availableLtps,
- busy: false
- };
- } else {
- state = {
- ...state,
- busy: false
+ busy: false,
+ loadedOnce: true
};
}
+ } else if (action instanceof SetInitialLoadedAction) {
+
+ state = {
+ ...state,
+ loadedOnce: action.initialLoaded
+ };
+ } else {
+ state = {
+ ...state,
+ busy: false
+ };
}
+
return state;
}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
index c33f10a7e..e57f3860c 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts
@@ -37,6 +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';
export interface IPerformanceHistoryStoreState {
nodeId: string;
@@ -51,6 +53,7 @@ export interface IPerformanceHistoryStoreState {
crossPolarDiscrimination: ICrossPolarDiscriminationState;
currentOpenPanel: string | null;
pmDataIntervalType: PmDataInterval;
+ subViews: toggleViewDataType;
}
const mountIdHandler: IActionHandler<string> = (state = "", action) => {
@@ -78,6 +81,29 @@ const currentPMDataIntervalHandler: IActionHandler<PmDataInterval> = (state = Pm
return state;
}
+
+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) => {
+
+ 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;
+ }
+ } else if (action instanceof ResetAllSubViewsAction) {
+ state = { performanceDataSelection: "chart", adaptiveModulation: "chart", receiveLevelDataSelection: "chart", transmissionPower: "chart", temperatur: "chart", SINR: "chart", CPD: "chart" }
+ }
+
+ return state;
+}
+
declare module '../../../../framework/src/store/applicationStore' {
interface IApplicationStoreState {
performanceHistory: IPerformanceHistoryStoreState;
@@ -97,7 +123,8 @@ const actionHandlers = {
signalToInterference: signalToInterferenceActionHandler,
crossPolarDiscrimination: crossPolarDiscriminationActionHandler,
currentOpenPanel: currentOpenPanelHandler,
- pmDataIntervalType: currentPMDataIntervalHandler
+ pmDataIntervalType: currentPMDataIntervalHandler,
+ subViews: toogleViewDataHandler
};
const performanceHistoryRootHandler = combineActionHandler<IPerformanceHistoryStoreState>(actionHandlers);
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts
new file mode 100644
index 000000000..f705e10b2
--- /dev/null
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/models/toggleDataType.ts
@@ -0,0 +1,25 @@
+/**
+ * ============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==========================================================================
+ */
+
+/**
+ * Specifies possible sub views
+ */
+export type SubTabType = "chart" | "table";
+
+export type currentViewType = "performanceData" | "receiveLevel" | "transmissionPower" | "adaptiveModulation" | "Temp" | "SINR" | "CPD";
+
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
index 3240f73f1..f58638e30 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/utils/chartUtils.tsx
@@ -22,7 +22,7 @@ import * as moment from 'moment';
import { ITimeStamp } from 'models/chartTypes';
const style: React.CSSProperties = {
- height: "350px"
+ height: "80%"
}
export const lineChart = (chartPagedData: IDataSetsObject) => {
return (
diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
index ae22f8041..4984e80c3 100644
--- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
+++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx
@@ -24,7 +24,7 @@ import Select from '@material-ui/core/Select';
import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { Panel } from '../../../../framework/src/components/material-ui';
+import { Panel, Loader } from '../../../../framework/src/components/material-ui';
import { NavigateToApplication } from '../../../../framework/src/actions/navigationActions';
import { Dispatch } from '../../../../framework/src/flux/store';
@@ -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 } from '../actions/ltpAction';
+import { loadDistinctLtpsbyNetworkElementAsync, SetInitialLoadedAction } from '../actions/ltpAction';
import { SetPanelAction } from '../actions/panelChangeActions';
import { createPerformanceDataPreActions, performanceDataReloadAction, createPerformanceDataActions } from '../handlers/performanceDataHandler';
import { createReceiveLevelPreActions, receiveLevelReloadAction, createReceiveLevelActions } from '../handlers/receiveLevelHandler';
@@ -50,6 +50,9 @@ import { createSignalToInterferencePreActions, signalToInterferenceReloadAction,
import { createCrossPolarDiscriminationPreActions, crossPolarDiscriminationReloadAction, createCrossPolarDiscriminationActions } from '../handlers/crossPolarDiscriminationHandler';
import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table';
+import { AppBar, Tabs, Tab } from '@material-ui/core';
+import LtpSelection from '../components/ltpSelection';
+import { ResetAllSubViewsAction } from '../actions/toggleActions';
const PerformanceHistoryComponentStyles = (theme: Theme) => createStyles({
root: {
@@ -58,19 +61,6 @@ const PerformanceHistoryComponentStyles = (theme: Theme) => createStyles({
},
margin: {
margin: theme.spacing(1),
- },
- display: {
- display: "inline-block"
- },
- selectDropdown: {
- borderRadius: 1,
- position: "relative",
- backgroundColor: theme.palette.background.paper,
- border: "1px solid #ced4da",
- fontSize: 16,
- width: "auto",
- padding: "5px 26px 5px 12px",
- transition: theme.transitions.create(["border-color", "box-shadow"]),
}
});
@@ -79,6 +69,7 @@ const mapProps = (state: IApplicationStoreState) => ({
activePanel: state.performanceHistory.currentOpenPanel,
availableLtps: state.performanceHistory.ltps.distinctLtps,
networkElements: state.performanceHistory.networkElements.deviceList,
+ initialLoaded: state.performanceHistory.ltps.loadedOnce
});
const mapDispatcher = (dispatcher: IDispatcher) => ({
@@ -111,7 +102,9 @@ const mapDispatcher = (dispatcher: IDispatcher) => ({
timeIntervalChange: (time: PmDataInterval) => dispatcher.dispatch(new TimeChangeAction(time)),
changeNode: (nodeId: string) => dispatcher.dispatch((dispatch: Dispatch) => {
dispatch(new NavigateToApplication("performanceHistory", nodeId));
- })
+ }),
+ setInitialLoaded: (isLoaded: boolean) => dispatcher.dispatch((dispatch: Dispatch) => { dispatch(new SetInitialLoadedAction(isLoaded)); }),
+ resetSubViews: () => dispatcher.dispatch(new ResetAllSubViewsAction())
});
export type NetworkElementType = {
@@ -127,7 +120,12 @@ type PerformanceHistoryComponentState = {
selectedLtp: string,
showNetworkElementsTable: boolean,
showLtps: boolean,
- showPanels: boolean
+ showPanels: boolean,
+ preFilter:
+ {
+ "node-name": string,
+ "uuid-interface": string
+ } | {}
};
/**
@@ -145,34 +143,70 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
selectedLtp: "-1",
showNetworkElementsTable: true,
showLtps: false,
- showPanels: false
+ showPanels: false,
+ preFilter: {}
};
}
- onTogglePanel = (panelId: PanelId) => {
- const nextActivePanel = panelId === this.props.activePanel ? null : panelId;
+ onChangeTabs = (event: React.ChangeEvent<{}>, newValue: PanelId) => {
+ const nextActivePanel = newValue;
+ this.changeTabs(nextActivePanel);
+ }
+
+ changeTabs = (nextActivePanel: PanelId) => {
this.props.setCurrentPanel(nextActivePanel);
+ const preFilter = this.state.preFilter;
switch (nextActivePanel) {
case "PerformanceData":
- this.props.reloadPerformanceData();
+ if (this.props.performanceData.preFilter !== {} && this.props.performanceData.preFilter === preFilter) {
+ this.props.reloadPerformanceData();
+ } else {
+ this.props.performanceDataPreActions.onPreFilterChanged(preFilter);
+ }
break;
case "ReceiveLevel":
- this.props.reloadReceiveLevel();
+ if (this.props.receiveLevel.preFilter !== {} && this.props.receiveLevel.preFilter === preFilter) {
+ this.props.reloadReceiveLevel();
+ }
+ else {
+ this.props.receiveLevelPreActions.onPreFilterChanged(preFilter);
+ }
break;
case "TransmissionPower":
- this.props.reloadTransmissionPower();
+ if (this.props.transmissionPower.preFilter !== {} && this.props.transmissionPower.preFilter === preFilter) {
+ this.props.reloadTransmissionPower();
+ }
+ else {
+ this.props.transmissionPowerPreActions.onPreFilterChanged(preFilter);
+ }
break;
case "AdaptiveModulation":
- this.props.reloadAdaptiveModulation();
+ if (this.props.adaptiveModulation.preFilter !== {} && this.props.adaptiveModulation.preFilter === preFilter) {
+ this.props.reloadAdaptiveModulation();
+ } else {
+ this.props.adaptiveModulationPreActions.onPreFilterChanged(preFilter);
+ }
break;
case "Temperature":
- this.props.reloadTemperature();
+ if (this.props.temperature.preFilter !== {} && this.props.temperature.preFilter === preFilter) {
+ this.props.reloadTemperature();
+ } else {
+ this.props.temperaturePreActions.onPreFilterChanged(preFilter);
+ }
break;
case "SINR":
- this.props.reloadSignalToInterference();
+ if (this.props.signalToInterference.preFilter !== {} && this.props.signalToInterference.preFilter === preFilter) {
+ this.props.reloadSignalToInterference();
+ } else {
+ this.props.signalToInterferencePreActions.onPreFilterChanged(preFilter);
+ }
break;
case "CPD":
- this.props.reloadCrossPolarDiscrimination();
+ if (this.props.crossPolarDiscrimination.preFilter !== {} && this.props.crossPolarDiscrimination.preFilter === preFilter) {
+ this.props.reloadCrossPolarDiscrimination();
+ } else {
+ this.props.crossPolarDiscriminationPreActions.onPreFilterChanged(preFilter);
+ }
break;
default:
// do nothing if all panels are closed
@@ -181,7 +215,6 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
}
render(): JSX.Element {
- const { classes } = this.props;
const { activePanel, nodeId } = this.props;
if (nodeId === "") {
return (
@@ -194,59 +227,70 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
)
}
else {
- 3
this.handleURLChange(nodeId);
return (
<>
- <h3>Selected Network Element: {this.state.selectedNetworkElement} </h3>
- {this.state.showLtps && (
- <div>
- <FormControl className={classes.display}>
- <span>
- Select LTP
- </span>
- <Select className={classes.selectDropdown} value={this.state.selectedLtp} onChange={this.handleLtpChange} >
- <MenuItem value={"-1"}><em>--Select--</em></MenuItem>
- {this.props.availableLtps.map(ltp =>
- (<MenuItem value={ltp.key} key={ltp.key}>{ltp.key}</MenuItem>))}
- </Select>
- <span> Time-Period </span>
- <Select className={classes.selectDropdown} value={this.state.selectedTimePeriod} onChange={this.handleTimePeriodChange} >
- <MenuItem value={"15min"}>15min</MenuItem>
- <MenuItem value={"24hours"}>24hours</MenuItem>
- </Select>
- </FormControl>
- {this.state.showPanels && (
- <div>
- <Panel activePanel={activePanel} panelId={"PerformanceData"} onToggle={this.onTogglePanel} title={"Performance Data"}>
- <PerformanceData selectedTimePeriod={this.state.selectedTimePeriod} />
- </Panel>
- <Panel activePanel={activePanel} panelId={"ReceiveLevel"} onToggle={this.onTogglePanel} title={"Receive Level"}>
- <ReceiveLevel selectedTimePeriod={this.state.selectedTimePeriod} />
- </Panel>
- <Panel activePanel={activePanel} panelId={"TransmissionPower"} onToggle={this.onTogglePanel} title={"Transmission Power"}>
- <TransmissionPower selectedTimePeriod={this.state.selectedTimePeriod} />
- </Panel>
- <Panel activePanel={activePanel} panelId={"AdaptiveModulation"} onToggle={this.onTogglePanel} title={"Adaptive Modulation"}>
- <AdaptiveModulation selectedTimePeriod={this.state.selectedTimePeriod} />
- </Panel>
- <Panel activePanel={activePanel} panelId={"Temperature"} onToggle={this.onTogglePanel} title={"Temperature"}>
- <Temperature selectedTimePeriod={this.state.selectedTimePeriod} />
- </Panel>
- <Panel activePanel={activePanel} panelId={"SINR"} onToggle={this.onTogglePanel} title={"Signal-to-interference-plus-noise ratio (SINR)"}>
- <SignalToInterference selectedTimePeriod={this.state.selectedTimePeriod} />
- </Panel>
- <Panel activePanel={activePanel} panelId={"CPD"} onToggle={this.onTogglePanel} title={"Cross Polar Discrimination"}>
- <CrossPolarDiscrimination selectedTimePeriod={this.state.selectedTimePeriod} />
- </Panel>
- </div>
- )}
- </div>
- )}
+ {this.state.showLtps &&
+
+ <LtpSelection 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}
+ />
+ }
+ {this.state.showPanels &&
+ <>
+
+ <AppBar position="static" >
+ <Tabs value={activePanel} onChange={this.onChangeTabs} variant="scrollable" scrollButtons="auto" aria-label="performance data tabs">
+ <Tab label="Performance Data" value="PerformanceData" />
+ <Tab label="Receive Level" value="ReceiveLevel" />
+ <Tab label="Transmission Power" value="TransmissionPower" />
+ <Tab label="Adaptive Modulation" value="AdaptiveModulation" />
+ <Tab label="Temperature" value="Temperature" />
+ <Tab label="Signal-to-interference-plus-noise ratio (SINR)" value="SINR" />
+ <Tab label="Cross Polar Discrimination" value="CPD" />
+ </Tabs>
+ </AppBar>
+ {
+ activePanel === "PerformanceData" &&
+ <PerformanceData selectedTimePeriod={this.state.selectedTimePeriod} />
+ }
+
+ {
+ activePanel === "ReceiveLevel" &&
+ <ReceiveLevel selectedTimePeriod={this.state.selectedTimePeriod} />
+ }
+
+ {
+ activePanel === "TransmissionPower" &&
+ <TransmissionPower selectedTimePeriod={this.state.selectedTimePeriod} />
+ }
+
+ {
+ activePanel === "AdaptiveModulation" &&
+ <AdaptiveModulation selectedTimePeriod={this.state.selectedTimePeriod} />
+ }
+ {
+ activePanel === "Temperature" &&
+ <Temperature selectedTimePeriod={this.state.selectedTimePeriod} />
+ }
+
+ {
+ activePanel === "SINR" &&
+ <SignalToInterference selectedTimePeriod={this.state.selectedTimePeriod} />
+ }
+
+ {
+ activePanel === "CPD" &&
+ <CrossPolarDiscrimination selectedTimePeriod={this.state.selectedTimePeriod} />
+ }
+ </>
+ }
</>
- );
+ )
}
- };
+ }
+
public componentDidMount() {
this.props.getAllDevicesPMdata();
@@ -257,6 +301,8 @@ 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();
}
/**
@@ -268,23 +314,53 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
selectedLtp: firstLtp
});
this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, firstLtp);
+ this.changeTabs("PerformanceData");
}
/**
- * A function which loads the tables based on prefilters defined by network element and ltp on selected time period.
+ * A function which reloads the visible table, if available, based on prefilters defined by network element and ltp on selected time period.
*/
private preFilterChangeAndReload = (networkElement: string, timePeriod: string, ltp: string) => {
- const preFilter = {
+ const newPreFilter = {
"node-name": networkElement,
"uuid-interface": ltp
};
- this.props.performanceDataPreActions.onPreFilterChanged(preFilter);
- this.props.receiveLevelPreActions.onPreFilterChanged(preFilter);
- this.props.transmissionPowerPreActions.onPreFilterChanged(preFilter);
- this.props.adaptiveModulationPreActions.onPreFilterChanged(preFilter);
- this.props.temperaturePreActions.onPreFilterChanged(preFilter);
- this.props.signalToInterferencePreActions.onPreFilterChanged(preFilter);
- this.props.crossPolarDiscriminationPreActions.onPreFilterChanged(preFilter);
+
+ const activePanel = this.props.activePanel;
+
+ if (this.props.activePanel !== null) {
+ // set prefilter and reload data if panel is open
+
+ switch (activePanel) {
+ case "PerformanceData":
+ this.props.performanceDataPreActions.onPreFilterChanged(newPreFilter);
+ break;
+ case "ReceiveLevel":
+ this.props.receiveLevelPreActions.onPreFilterChanged(newPreFilter);
+ break;
+ case "TransmissionPower":
+ this.props.transmissionPowerPreActions.onPreFilterChanged(newPreFilter);
+ break;
+ case "AdaptiveModulation":
+ this.props.adaptiveModulationPreActions.onPreFilterChanged(newPreFilter);
+ break;
+ case "Temperature":
+ this.props.temperaturePreActions.onPreFilterChanged(newPreFilter);
+ break;
+ case "SINR":
+ this.props.signalToInterferencePreActions.onPreFilterChanged(newPreFilter);
+ break;
+ case "CPD":
+ this.props.crossPolarDiscriminationPreActions.onPreFilterChanged(newPreFilter);
+ break;
+ default:
+ // do nothing if all panels are closed
+ break;
+ }
+ }
+
+ // set prefilter
+ this.setState({ preFilter: newPreFilter })
}
@@ -300,12 +376,19 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
showPanels: false,
selectedLtp: "-1"
});
+
+ this.props.setInitialLoaded(false);
+ this.props.resetSubViews();
+ this.setState({ preFilter: {} });
this.props.changeNode(selectedNetworkElement);
this.props.getDistinctLtpsIds(selectedNetworkElement, this.state.selectedTimePeriod, "-1", this.selectFirstLtp);
}
private handleURLChange = (selectedNetworkElement: string) => {
+
if (selectedNetworkElement !== this.state.selectedNetworkElement) {
+ // gets called if page is reloaded / opened with a networkname in the url,
+ // not if the selected networkelement is changed
this.setState({
showLtps: true,
selectedNetworkElement: selectedNetworkElement,
@@ -324,6 +407,7 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
if (ltpNotSelected) {
this.setState({
selectedLtp: "-1",
+ showPanels: false
});
}
}
@@ -332,21 +416,16 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
* Function which handles the time period changes.
*/
private handleTimePeriodChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
+
const selectedTimeInterval = event.target.value === "15min"
? PmDataInterval.pmInterval15Min
- : PmDataInterval.pmInterval24Hours
+ : PmDataInterval.pmInterval24Hours;
this.setState({
selectedTimePeriod: event.target.value,
});
+
this.props.timeIntervalChange(selectedTimeInterval);
- this.props.reloadPerformanceData();
- this.props.reloadReceiveLevel();
- this.props.reloadTransmissionPower();
- this.props.reloadAdaptiveModulation();
- this.props.reloadTemperature();
- this.props.reloadSignalToInterference();
- this.props.reloadCrossPolarDiscrimination();
this.props.getDistinctLtpsIds(this.state.selectedNetworkElement, event.target.value, this.state.selectedLtp, undefined, this.resetLtpDropdown);
this.preFilterChangeAndReload(this.state.selectedNetworkElement, event.target.value, this.state.selectedLtp);
}
@@ -355,15 +434,22 @@ class PerformanceHistoryComponent extends React.Component<PerformanceHistoryComp
* Function which handles the ltp changes.
*/
private handleLtpChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
- var showPanels: boolean = true;
+
if (event.target.value === "-1") {
- showPanels = false;
+ this.setState({
+ showPanels: false,
+ selectedLtp: event.target.value
+ });
+ this.props.setCurrentPanel(null);
+
+ } else if (event.target.value !== this.state.selectedLtp) {
+ this.setState({
+ showPanels: true,
+ selectedLtp: event.target.value
+ });
+ this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, event.target.value);
+
}
- this.setState({
- showPanels: showPanels,
- selectedLtp: event.target.value
- });
- this.preFilterChangeAndReload(this.state.selectedNetworkElement, this.state.selectedTimePeriod, event.target.value);
}
}
diff --git a/sdnr/wt/odlux/framework/pom.xml b/sdnr/wt/odlux/framework/pom.xml
index 39856c5c0..15f71f20a 100644
--- a/sdnr/wt/odlux/framework/pom.xml
+++ b/sdnr/wt/odlux/framework/pom.xml
@@ -46,7 +46,7 @@
<properties>
<buildtime>${maven.build.timestamp}</buildtime>
<distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion>
- <buildno>40.4a1f067(20/02/11)</buildno>
+ <buildno>41.0f8da02(20/02/20)</buildno>
<odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version>
</properties>
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
index 2075e052c..8ea0a93f4 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx
@@ -35,6 +35,9 @@ const styles = (theme: Theme) => createStyles({
input: {
margin: theme.spacing(1),
},
+ numberInput: {
+ float: "right"
+ }
});
interface IEnhancedTableFilterComponentProps extends WithStyles<typeof styles> {
@@ -62,6 +65,7 @@ class EnhancedTableFilterComponent extends React.Component<IEnhancedTableFilterC
const style = col.width ? { width: col.width } : {};
return (
<TableCell
+ className={col.type === ColumnType.numeric ? classes.numberInput : ''}
key={col.property}
padding={col.disablePadding ? 'none' : 'default'}
style={style}
diff --git a/sdnr/wt/odlux/framework/src/views/login.tsx b/sdnr/wt/odlux/framework/src/views/login.tsx
index 3f6ef6134..fa01568ea 100644
--- a/sdnr/wt/odlux/framework/src/views/login.tsx
+++ b/sdnr/wt/odlux/framework/src/views/login.tsx
@@ -18,13 +18,9 @@
import * as React from 'react';
import { withRouter, RouteComponentProps } from 'react-router-dom';
+import Alert from '@material-ui/lab/Alert';
import Avatar from '@material-ui/core/Avatar';
import Button from '@material-ui/core/Button';
-import Dialog from '@material-ui/core/Dialog';
-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 CssBaseline from '@material-ui/core/CssBaseline';
import FormControl from '@material-ui/core/FormControl';
import FormControlLabel from '@material-ui/core/FormControlLabel';
@@ -102,7 +98,7 @@ class LoginComponent extends React.Component<LoginProps, ILoginState> {
render(): JSX.Element {
const { classes } = this.props;
return (
- <React.Fragment>
+ <>
<CssBaseline />
<main className={classes.layout}>
<Paper className={classes.paper}>
@@ -157,27 +153,10 @@ class LoginComponent extends React.Component<LoginProps, ILoginState> {
Sign in
</Button>
</form>
+ {this.state.message && <Alert severity="error">{this.state.message}</Alert>}
</Paper>
</main>
- <Dialog
- open={!!this.state.message}
- onClose={() => { this.setState({ message: '' }) }}
- aria-labelledby="alert-dialog-title"
- aria-describedby="alert-dialog-description"
- >
- <DialogTitle id="alert-dialog-title">{"Error"}</DialogTitle>
- <DialogContent>
- <DialogContentText id="alert-dialog-description">
- {this.state.message}
- </DialogContentText>
- </DialogContent>
- <DialogActions>
- <Button onClick={() => { this.setState({ message: '' }) }} color="secondary" autoFocus>
- OK
- </Button>
- </DialogActions>
- </Dialog>
- </React.Fragment>
+ </>
);
}
diff --git a/sdnr/wt/odlux/package.json b/sdnr/wt/odlux/package.json
index c6acd563c..b9764f090 100644
--- a/sdnr/wt/odlux/package.json
+++ b/sdnr/wt/odlux/package.json
@@ -16,6 +16,7 @@
"@fortawesome/react-fontawesome": "0.1.3",
"@material-ui/core": "4.9.0",
"@material-ui/icons": "4.5.1",
+ "@material-ui/lab": "4.0.0-alpha.41",
"@types/classnames": "2.2.6",
"@types/flux": "3.1.8",
"@types/jquery": "3.3.10",
@@ -81,4 +82,4 @@
"webpack-cli": "3.2.1",
"webpack-dev-server": "3.1.14"
}
-}
+} \ No newline at end of file