Update odlux
Update performance app: fix scrolling bug, reduce loading times, update ui to use tabs instead of panels, change the view to toggle between chart and table to better visualize data, minior bugfixes for other apps
Issue-ID: SDNC-1080
Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
Change-Id: I2b5cf3a5f580f4193421bc047e5256d8e9497e6b
Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com>
diff --git a/sdnr/wt/data-provider/provider/pom.xml b/sdnr/wt/data-provider/provider/pom.xml
index ffbd221..2742d70 100644
--- a/sdnr/wt/data-provider/provider/pom.xml
+++ b/sdnr/wt/data-provider/provider/pom.xml
@@ -52,7 +52,7 @@
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
<buildtime>${maven.build.timestamp}</buildtime>
<databaseport>49402</databaseport>
- <odlux.buildno>39.0e1988b(20/01/12)</odlux.buildno>
+ <odlux.buildno>41.0f8da02(20/02/20)</odlux.buildno>
</properties>
<dependencies>
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts b/sdnr/wt/odlux/apps/configurationApp/src/yang/yangParser.ts
index 49c2b9b..5322e1f 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 @@
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 @@
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 @@
private _groupingsToResolve: (() => void)[] = [];
private _identityToResolve: (() => void)[] = [];
private _unionsToResolve: (() => void)[] = [];
-
+ private _modulesToResolve: (() => void)[] = [];
private _modules: { [name: string]: Module } = {};
private _views: ViewSpecification[] = [{
@@ -398,14 +407,16 @@
// 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 @@
console.warn(error.message);
}
});
+
+ this._modulesToResolve.forEach(cb => {
+ try { cb(); } catch (error) {
+ console.warn(error.message);
+ }
+ });
};
private _nextId = 1;
@@ -580,8 +597,16 @@
}
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
// 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 @@
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 @@
}
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 @@
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 @@
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 0370df7..45003e7 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 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 @@
};
}
+ 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 @@
});
}
};
- let counter = 0;
+
return (
<>
<NetworkElementTable stickyHeader tableId="network-element-table" customActionButtons={[addRequireNetworkElementAction]} columns={[
@@ -124,24 +156,8 @@
{ 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 @@
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 5adc9d4..cbcfd84 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 @@
}
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 e0cd514..5ffd987 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 @@
} 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 @@
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 @@
{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 @@
</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 @@
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 882a6b3..d520db4 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 @@
<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 @@
}} > {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 2741d88..3756175 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 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 0000000..1f53a58
--- /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 09d3acc..c626986 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 { 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 @@
* 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 @@
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 267e00b..7489757 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 { 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 @@
* 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 @@
});
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 0000000..8327ec4
--- /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 c58c49c..d0caa6f 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 { 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 @@
* 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 @@
});
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 55bc398..4b0a835 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 { 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 @@
* 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 @@
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 42aa007..ba480d5 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 { 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 @@
* 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 @@
});
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 256911c..28f75d8 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 { 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 @@
* 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 @@
});
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 0000000..97a2006
--- /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 635cbf1..6fe66d2 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 { 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 @@
* 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 @@
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 b3b284b..fd137fe 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 {
AllAvailableLtpsLoadedAction,
LoadAllAvailableLtpsAction,
+ SetInitialLoadedAction,
} from '../actions/ltpAction';
import { LtpIds } from '../models/availableLtps';
@@ -27,11 +28,13 @@
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 @@
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 c33f10a..e57f386 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 { 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 @@
crossPolarDiscrimination: ICrossPolarDiscriminationState;
currentOpenPanel: string | null;
pmDataIntervalType: PmDataInterval;
+ subViews: toggleViewDataType;
}
const mountIdHandler: IActionHandler<string> = (state = "", action) => {
@@ -78,6 +81,29 @@
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 @@
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 0000000..f705e10
--- /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 3240f73..f58638e 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 { 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 ae22f80..4984e80 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 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 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 { 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 @@
},
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 @@
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 @@
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 @@
selectedLtp: string,
showNetworkElementsTable: boolean,
showLtps: boolean,
- showPanels: boolean
+ showPanels: boolean,
+ preFilter:
+ {
+ "node-name": string,
+ "uuid-interface": string
+ } | {}
};
/**
@@ -145,34 +143,70 @@
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 @@
}
render(): JSX.Element {
- const { classes } = this.props;
const { activePanel, nodeId } = this.props;
if (nodeId === "") {
return (
@@ -194,59 +227,70 @@
)
}
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 @@
this.props.enableFilterAdaptiveModulation.onToggleFilter();
this.props.enableFilterSinr.onToggleFilter();
this.props.enableFilterCpd.onToggleFilter();
+ this.props.setInitialLoaded(false);
+ this.props.resetSubViews();
}
/**
@@ -268,23 +314,53 @@
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 @@
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 @@
if (ltpNotSelected) {
this.setState({
selectedLtp: "-1",
+ showPanels: false
});
}
}
@@ -332,21 +416,16 @@
* 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 @@
* 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 39856c5..15f71f2 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 2075e05..8ea0a93 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 @@
input: {
margin: theme.spacing(1),
},
+ numberInput: {
+ float: "right"
+ }
});
interface IEnhancedTableFilterComponentProps extends WithStyles<typeof styles> {
@@ -62,6 +65,7 @@
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 3f6ef61..fa01568 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 @@
render(): JSX.Element {
const { classes } = this.props;
return (
- <React.Fragment>
+ <>
<CssBaseline />
<main className={classes.layout}>
<Paper className={classes.paper}>
@@ -157,27 +153,10 @@
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 c6acd56..b9764f0 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