From 889c7fbc0f78eadc302e8849ea7e6cad795e0d6e Mon Sep 17 00:00:00 2001 From: Aijana Schumann Date: Fri, 28 Feb 2020 15:15:26 +0100 Subject: update odlux stage 3 PerformanceApp: Add filter to chart view add scrolling header to tables, add basic validation to editNetworkElementDialog bugfixes Issue-ID: SDNC-1087 Signed-off-by: Aijana Schumann Change-Id: I585bd6cfeb11b867cd630e96e6479170d2f92fe8 --- .../src/views/configurationApplication.tsx | 15 ++- .../src/views/networkElementSelector.tsx | 2 +- .../src/components/editNetworkElementDialog.tsx | 79 +++++++++++++--- .../connectApp/src/components/networkElements.tsx | 4 +- .../src/models/networkElementConnection.ts | 9 +- .../odlux/apps/eventLogApp/src/views/eventLog.tsx | 4 +- .../faultApp/src/actions/panelChangeActions.ts | 6 ++ .../faultApp/src/handlers/faultAppRootHandler.ts | 13 ++- sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx | 16 +++- .../apps/faultApp/src/views/faultApplication.tsx | 25 +++-- .../odlux/apps/inventoryApp/src/fakeData/index.ts | 60 ++++++++++++ .../apps/inventoryApp/src/models/inventory.ts | 11 +++ .../inventoryApp/src/services/inventoryService.ts | 37 ++++++++ .../apps/inventoryApp/src/views/dashboard.tsx | 44 ++++++++- sdnr/wt/odlux/apps/inventoryApp/webpack.config.js | 10 +- .../maintenanceApp/src/views/maintenenceView.tsx | 24 ++--- .../mediatorApp/src/views/mediatorApplication.tsx | 2 +- .../src/views/mediatorServerSelection.tsx | 2 +- .../performanceHistoryApp/src/actions/ltpAction.ts | 16 ++++ .../src/actions/toggleActions.ts | 24 +++++ .../src/components/adaptiveModulation.tsx | 22 +++-- .../src/components/chartFilter.tsx | 50 ++++++++++ .../src/components/crossPolarDiscrimination.tsx | 20 ++-- .../src/components/ltpSelection.tsx | 22 ++++- .../src/components/performanceData.tsx | 20 ++-- .../src/components/receiveLevel.tsx | 23 +++-- .../src/components/signalToInterference.tsx | 20 ++-- .../src/components/temperature.tsx | 22 +++-- .../src/components/toggleContainer.tsx | 70 +++++++++++--- .../src/components/transmissionPower.tsx | 22 +++-- .../src/handlers/availableLtpsActionHandler.ts | 34 ++++++- .../src/handlers/performanceHistoryRootHandler.ts | 48 +++++++--- .../src/services/performanceHistoryService.ts | 2 +- .../src/views/performanceHistoryApplication.tsx | 21 +++-- sdnr/wt/odlux/framework/pom.xml | 2 +- .../src/components/material-table/index.tsx | 3 +- .../src/components/material-table/tableFilter.tsx | 6 +- .../framework/src/components/material-ui/index.ts | 2 +- .../src/components/material-ui/treeView.tsx | 102 +++++++++++---------- .../framework/src/components/navigationMenu.tsx | 7 ++ sdnr/wt/odlux/framework/src/views/test.tsx | 25 ++--- sdnr/wt/odlux/package.json | 7 +- 42 files changed, 713 insertions(+), 240 deletions(-) create mode 100644 sdnr/wt/odlux/apps/inventoryApp/src/fakeData/index.ts create mode 100644 sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts create mode 100644 sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx (limited to 'sdnr/wt/odlux') diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx index 9c92ceb6b..06de39b9d 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx +++ b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx @@ -65,13 +65,18 @@ const styles = (theme: Theme) => createStyles({ }, outer: { "flex": "1", - "heigh": "100%", + "height": "100%", "display": "flex", "alignItems": "center", "justifyContent": "center", }, inner: { + }, + container: { + "height": "100%", + "display": "flex", + "flexDirection": "column", }, "icon": { "marginRight": theme.spacing(0.5), @@ -440,7 +445,7 @@ class ConfigurationApplicationComponent extends React.Component[]>((acc, cur) => { const elm = listElements[cur]; if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) { @@ -571,8 +576,8 @@ class ConfigurationApplicationComponent extends React.Component - + []>((acc, cur) => { const elm = listSpecification.elements[cur]; if (elm.uiType !== "object" && listData.every(entry => entry[elm.label] != null)) { @@ -594,7 +599,7 @@ class ConfigurationApplicationComponent extends React.Component +
{this.renderBreadCrumps()} {displayAsList && viewData instanceof Array ? this.renderUIViewList(viewSpecification, keyProperty!, viewData) diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx index 8155becbb..c153ed5a1 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx +++ b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx @@ -47,7 +47,7 @@ class NetworkElementSelectorComponent extends React.Component { this.props.history.push(`${this.props.match.path}/${row.nodeId}`) }} columns={[ + { this.props.history.push(`${this.props.match.path}/${row.nodeId}`) }} columns={[ { property: "nodeId", title: "Name", type: ColumnType.text }, { property: "isRequired", title: "Required ?", type: ColumnType.boolean }, { property: "host", title: "Host", type: ColumnType.text }, diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx index ce7f48cc9..e3b640120 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/components/editNetworkElementDialog.tsx @@ -24,7 +24,7 @@ import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogContentText from '@material-ui/core/DialogContentText'; import DialogTitle from '@material-ui/core/DialogTitle'; -import { FormControl, InputLabel, Select, MenuItem } from '@material-ui/core'; +import { FormControl, InputLabel, Select, MenuItem, Typography } from '@material-ui/core'; import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/connect'; @@ -35,7 +35,7 @@ import { } from '../actions/networkElementsActions'; import { unmountNetworkElementAsyncActionCreator, mountNetworkElementAsyncActionCreator } from '../actions/mountedNetworkElementsActions'; -import { NetworkElementConnection, UpdateNetworkElement } from '../models/networkElementConnection'; +import { NetworkElementConnection, UpdateNetworkElement, propertyOf } from '../models/networkElementConnection'; import { removeWebUriAction } from '../actions/commonNetworkElementsActions'; export enum EditNetworkElementDialogMode { @@ -47,6 +47,8 @@ export enum EditNetworkElementDialogMode { UnmountNetworkElement = "unmountNetworkElement", } + + const mapDispatch = (dispatcher: IDispatcher) => ({ addNewNetworkElement: async (element: NetworkElementConnection) => { await dispatcher.dispatch(addNewNetworkElementAsyncActionCreator(element)); @@ -57,8 +59,21 @@ const mapDispatch = (dispatcher: IDispatcher) => ({ dispatcher.dispatch(unmountNetworkElementAsyncActionCreator(element && element.nodeId)); }, editNetworkElement: async (element: UpdateNetworkElement, mountElement: NetworkElementConnection) => { - await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element)); - await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement)); + + const values = Object.keys(element); + + //make sure properties are there in case they get renamed + const idProperty = propertyOf("id"); + const isRequiredProperty = propertyOf("isRequired"); + + if (values.length === 2 && values.includes(idProperty as string) && values.includes(isRequiredProperty as string)) { + // do not mount network element, if only isRequired is changed + await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element)); + + } else { + await dispatcher.dispatch(editNetworkElementAsyncActionCreator(element)); + await dispatcher.dispatch(mountNetworkElementAsyncActionCreator(mountElement)); + } }, removeNetworkElement: async (element: UpdateNetworkElement) => { await dispatcher.dispatch(removeNetworkElementAsyncActionCreator(element)); @@ -140,7 +155,7 @@ type EditNetworkElementDialogComponentProps = Connect void; }; -type EditNetworkElementDialogComponentState = NetworkElementConnection; +type EditNetworkElementDialogComponentState = NetworkElementConnection & { isNameValid: boolean, isHostSet: boolean }; class EditNetworkElementDialogComponent extends React.Component { constructor(props: EditNetworkElementDialogComponentProps) { @@ -151,6 +166,8 @@ class EditNetworkElementDialogComponent extends React.Component { this.setState({ nodeId: event.target.value }); }} /> + {!this.state.isNameValid && Name cannot be empty.} { this.setState({ host: event.target.value }); }} /> + {!this.state.isHostSet && IP Adress cannot be empty.} { this.setState({ port: +event.target.value }); }} /> {setting.enableUsernameEditor && { this.setState({ username: event.target.value }); }} /> || null} {setting.enableUsernameEditor && { this.setState({ password: event.target.value }); }} /> || null} @@ -180,15 +199,18 @@ class EditNetworkElementDialogComponent extends React.Component @@ -230,10 +252,39 @@ class EditNetworkElementDialogComponent extends React.Component { this.props.onClose && this.props.onClose(); + this.setState({ password: '', username: '' }); + this.resetRequieredFields(); + } + + private resetRequieredFields() { + this.setState({ isNameValid: true, isHostSet: true }); + } + + private areRequieredFieldsValid() { + let areFieldsValid = true; + + if (this.state.nodeId == undefined || this.state.nodeId.trim().length === 0) { + this.setState({ isNameValid: false }); + areFieldsValid = false; + } else { + this.setState({ isNameValid: true }); + } + + if (this.state.host == undefined || this.state.host.trim().length === 0) { + this.setState({ isHostSet: false }); + areFieldsValid = false; + } else { + this.setState({ isHostSet: true }); + } + + return areFieldsValid; } static getDerivedStateFromProps(props: EditNetworkElementDialogComponentProps, state: EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection }): EditNetworkElementDialogComponentState & { _initialNetworkElement: NetworkElementConnection } { diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx index 45003e741..d50a81ed5 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx +++ b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx @@ -110,9 +110,7 @@ export class NetworkElementsListComponent extends React.Component, this.onOpenInfoNetworkElementDialog(event, rowData)} disabled={rowData.status === "Connecting" || rowData.status === "Disconnected"} >Info, this.onOpenEditNetworkElementDialog(event, rowData)}>Edit, - !rowData.isRequired - ? this.onOpenAddNetworkElementDialog(event, rowData)} >Add - : this.onOpenRemoveNetworkElementDialog(event, rowData)} >Remove, + this.onOpenRemoveNetworkElementDialog(event, rowData)} >Remove, , this.props.navigateToApplication("inventory", rowData.nodeId)}>Inventory, , diff --git a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts index f58dc58ab..b3586d693 100644 --- a/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts +++ b/sdnr/wt/odlux/apps/connectApp/src/models/networkElementConnection.ts @@ -51,4 +51,11 @@ export type UpdateNetworkElement = { export type ConnectionStatus = { status: string -} \ No newline at end of file +} + +/** + * Checks if a object has a given propertyname, if yes, the name is returned as string. + * @throws at compile time if property is not available + * @param name propertyname + */ +export const propertyOf = (name: keyof TObj) => name; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx b/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx index 535de1f1d..5993bb5c4 100644 --- a/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx +++ b/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx @@ -24,7 +24,7 @@ import { EventLogType } from '../models/eventLogType'; import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore"; import { createEventLogProperties, createEventLogActions } from "../handlers/eventLogHandler"; -const EventLogTable = MaterialTable as MaterialTableCtorType; +const EventLogTable = MaterialTable as MaterialTableCtorType; const mapProps = (state: IApplicationStoreState) => ({ eventLogProperties: createEventLogProperties(state), @@ -37,7 +37,7 @@ const mapDispatch = (dispatcher: IDispatcher) => ({ class EventLogComponent extends React.Component> { render() { - return { return new SetPanelAction(panelId); } diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts index dddb4a247..a5cf928fc 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts +++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts @@ -26,21 +26,26 @@ import { IActionHandler } from '../../../../framework/src/flux/action'; import { IFaultNotifications, faultNotificationsHandler } from './notificationsHandler'; import { ICurrentProblemsState, currentProblemsActionHandler } from './currentProblemsHandler'; import { IAlarmLogEntriesState, alarmLogEntriesActionHandler } from './alarmLogEntriesHandler'; -import { SetPanelAction } from '../actions/panelChangeActions'; +import { SetPanelAction, RememberCurrentPanelAction } from '../actions/panelChangeActions'; import { IFaultStatus, faultStatusHandler } from './faultStatusHandler'; import { stuckAlarmHandler } from './clearStuckAlarmsHandler'; +import { PanelId } from 'models/panelId'; export interface IFaultAppStoreState { currentProblems: ICurrentProblemsState; faultNotifications: IFaultNotifications; alarmLogEntries: IAlarmLogEntriesState; - currentOpenPanel: string | null; + currentOpenPanel: ICurrentOpenPanelState; faultStatus: IFaultStatus; } -const currentOpenPanelHandler: IActionHandler = (state = null, action) => { +type ICurrentOpenPanelState = { openPanel: string | null, savedPanel: PanelId | null }; +const panelInitState = { openPanel: null, savedPanel: null }; +const currentOpenPanelHandler: IActionHandler = (state = panelInitState, action) => { if (action instanceof SetPanelAction) { - state = action.panelId; + state = { ...state, openPanel: action.panelId }; + } else if (action instanceof RememberCurrentPanelAction) { + state = { ...state, savedPanel: action.panelId }; } return state; } diff --git a/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx index 02dde90f7..666667e40 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx +++ b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx @@ -40,6 +40,7 @@ import { AddFaultNotificationAction } from "./actions/notificationActions"; import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from "./handlers/currentProblemsHandler"; import { FaultStatus } from "./components/faultStatus"; import { refreshFaultStatusAsyncAction } from "./actions/statusActions"; +import { alarmLogEntriesReloadAction } from "./handlers/alarmLogEntriesHandler"; let currentMountId: string | undefined = undefined; @@ -49,7 +50,7 @@ const mapProps = (state: IApplicationStoreState) => ({ const mapDisp = (dispatcher: IDispatcher) => ({ currentProblemsActions: createCurrentProblemsActions(dispatcher.dispatch, true), - setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)) + setCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new SetPanelAction(panelId)), }); const FaultApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteComponentProps<{ mountId?: string }> & Connect) => { @@ -73,9 +74,9 @@ const FaultApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteCom const App = withRouter((props: RouteComponentProps) => ( - - - + + + )); export function register() { @@ -93,6 +94,13 @@ export function register() { const store = applicationApi && applicationApi.applicationStore; if (fault && store) { store.dispatch(new AddFaultNotificationAction(fault)); + + //reload fault data if tab is open + if (store.state.fault.currentOpenPanel.openPanel === "AlarmLog") { + store.dispatch(alarmLogEntriesReloadAction); + } else if (store.state.fault.currentOpenPanel.openPanel === "CurrentProblem") { + store.dispatch(currentProblemsReloadAction); + } } })); diff --git a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx index cbcfd84d6..ed395d2e4 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx +++ b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx @@ -33,13 +33,14 @@ import { PanelId } from '../models/panelId'; import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from '../handlers/currentProblemsHandler'; import { createAlarmLogEntriesProperties, createAlarmLogEntriesActions, alarmLogEntriesReloadAction } from '../handlers/alarmLogEntriesHandler'; -import { setPanelAction } from '../actions/panelChangeActions'; +import { setPanelAction, RememberCurrentPanelAction } from '../actions/panelChangeActions'; import { Tooltip, IconButton, AppBar, Tabs, Tab } from '@material-ui/core'; import RefreshIcon from '@material-ui/icons/Refresh'; import ClearStuckAlarmsDialog, { ClearStuckAlarmsDialogMode } from '../components/clearStuckAlarmsDialog'; const mapProps = (state: IApplicationStoreState) => ({ - panelId: state.fault.currentOpenPanel, + panelId: state.fault.currentOpenPanel.openPanel, + savedPanel: state.fault.currentOpenPanel.savedPanel, currentProblemsProperties: createCurrentProblemsProperties(state), faultNotifications: state.fault.faultNotifications, alarmLogEntriesProperties: createAlarmLogEntriesProperties(state) @@ -52,7 +53,8 @@ const mapDisp = (dispatcher: IDispatcher) => ({ reloadAlarmLogEntries: () => dispatcher.dispatch(alarmLogEntriesReloadAction), switchActivePanel: (panelId: PanelId) => { dispatcher.dispatch(setPanelAction(panelId)); - } + }, + rememberCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new RememberCurrentPanelAction(panelId)) }); type FaultApplicationComponentProps = RouteComponentProps & Connect; @@ -146,7 +148,7 @@ class FaultApplicationComponent extends React.Component () => new Promise(resolve => setTimeout(resolve, time, time)); + +const getTreeElements = (searchTerm: string | null, treeLevel: number = 0, parentUUID: string | null = null): [InventoryTreeNode, boolean] => { + const elements = (data.filter(e => e["tree-level"] === treeLevel && (!parentUUID || e["parent-uuid"] === parentUUID)) || []) + let elementMatch = false; + const treeeNode = elements.reduce((acc, cur) => { + const [children, childMatch] = getTreeElements(searchTerm, treeLevel + 1, cur["node-id"]); + const isMatch = searchTerm ? Object.keys(cur).some(k => String((cur as any)[k]).indexOf(searchTerm)) : false; + elementMatch = elementMatch || isMatch || childMatch; + if (!searchTerm || isMatch || childMatch) { + acc[cur["node-id"]] = { + label: cur["node-id"], + children: children, + isMatch: false, + }; + } + return acc; + }, {}); + + return [treeeNode, elementMatch] +}; + +export const getTree = async (searchTerm: string | null = null) : Promise => { + await deleay(600); + const [node] = getTreeElements(searchTerm); + return node; +}; + +export const getElement = async (id: string ): Promise => { + await deleay(600); + const res = data.find(e => e.id === id); + return res && convertPropertyNames(res, replaceHyphen) as unknown as InventoryType; +}; diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts index 9d747415f..c6b6c91cb 100644 --- a/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts +++ b/sdnr/wt/odlux/apps/inventoryApp/src/models/inventory.ts @@ -16,6 +16,7 @@ * ============LICENSE_END========================================================================== */ export { HitEntry, Result } from '../../../../framework/src/models'; + export type InventoryType = { treeLevel: number; parentUuid: string; @@ -32,3 +33,13 @@ export type InventoryType = { modelIdentifier: string; typeName: string; } + +export type InventoryTreeNode = { + [key: string]: { + label: string; + children?: InventoryTreeNode; + isMatch?: boolean; + ownSeverity?: string; + childrenSeveritySummary?: string; + } +} \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts b/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts new file mode 100644 index 000000000..252d6d425 --- /dev/null +++ b/sdnr/wt/odlux/apps/inventoryApp/src/services/inventoryService.ts @@ -0,0 +1,37 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ +import { requestRest } from '../../../../framework/src/services/restService'; + +import { InventoryTreeNode, InventoryType } from '../models/inventory'; +import { getTree, getElement } from '../fakeData'; + +/** + * Represents a web api accessor service for all maintenence entries related actions. + */ +class InventoryService { + public async getInventoryTree(searchTerm?: string): Promise { + return await getTree(searchTerm); + } + + public async getInventoryEntry(id: string): Promise { + return await getElement(id); + } + +} + +export const inventoryService = new InventoryService(); \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx index bd182ed5d..b63f628a3 100644 --- a/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx +++ b/sdnr/wt/odlux/apps/inventoryApp/src/views/dashboard.tsx @@ -16,14 +16,33 @@ * ============LICENSE_END========================================================================== */ import * as React from "react"; +import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect'; import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table'; +import { TreeView, TreeItem, TreeViewCtorType } from '../../../../framework/src/components/material-ui/treeView'; import { InventoryType } from '../models/inventory'; import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore"; import { createInventoryElementsProperties, createInventoryElementsActions } from "../handlers/inventoryElementsHandler"; +const styles = (theme: Theme) => createStyles({ + root: { + flex: "1 0 0%", + display: "flex", + flexDirection: "row", + }, + tree: { + flex: "1 0 0%", + minWidth: "250px", + padding: `0px ${theme.spacing(1)}px` + }, + details: { + flex: "5 0 0%", + padding: `0px ${theme.spacing(1)}px` + } +}); + const InventoryTable = MaterialTable as MaterialTableCtorType; const mapProps = (state: IApplicationStoreState) => ({ @@ -35,9 +54,28 @@ const mapDispatch = (dispatcher: IDispatcher) => ({ inventoryElementsActions: createInventoryElementsActions(dispatcher.dispatch) }); -class DashboardComponent extends React.Component> { +const SampleTree = TreeView as any as TreeViewCtorType; + + +type TreeDemoItem = TreeItem; + +const treeData: TreeDemoItem[] = [ + { + content: "Erste Ebene", children: [ + { + content: "Zweite Ebene", children: [ + { content: "Dritte Ebene" }, + ] + }, + { content: "Zweite Ebene 2" }, + ] + }, + { content: "Erste Ebene 3" }, +]; + +class DashboardComponent extends React.Component<& WithStyles & Connect> { render() { - return { colors: true }, proxy: { - "/oauth2/": { target: "http://localhost:48181", secure: false }, + "/yang-schema/": { + target: "http://localhost:48181", + secure: false + }, "/database/": { target: "http://localhost:48181", secure: false @@ -143,14 +146,13 @@ module.exports = (env) => { target: "http://localhost:48181", secure: false }, - "/websocket/": { + "/websocket": { target: "http://localhost:48181", ws: true, - changeOrigin: true, + changeOrigin: false, secure: false } } - } }]; } diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx index f557e5399..350bac221 100644 --- a/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx +++ b/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx @@ -37,7 +37,7 @@ import { MaintenenceEntry, spoofSymbol } from '../models/maintenenceEntryType'; import EditMaintenenceEntryDialog, { EditMaintenenceEntryDialogMode } from '../components/editMaintenenceEntryDialog'; import { convertToLocaleString } from '../utils/timeUtils'; -import { createmaintenanceEntriesActions, createmaintenanceEntriesProperties,maintenanceEntriesReloadAction } from '../handlers/maintenenceEntriesHandler'; +import { createmaintenanceEntriesActions, createmaintenanceEntriesProperties, maintenanceEntriesReloadAction } from '../handlers/maintenenceEntriesHandler'; const styles = (theme: Theme) => createStyles({ button: { @@ -60,7 +60,7 @@ const mapProps = (state: IApplicationStoreState) => ({ const mapDispatcher = (dispatcher: IDispatcher) => ({ maintenanceEntriesActions: createmaintenanceEntriesActions(dispatcher.dispatch), - onLoadMaintenanceEntries: async() => { + onLoadMaintenanceEntries: async () => { await dispatcher.dispatch(maintenanceEntriesReloadAction) } }); @@ -104,8 +104,8 @@ class MaintenenceViewComponent extends React.Component - ( rowData.active && (Date.parse(rowData.start).valueOf() <= now) && (Date.parse(rowData.end).valueOf() >= now) && || null - ) + ) }, { property: "active", title: "Activation State", type: ColumnType.boolean, labels: { "true": "active", "false": "not active" }, }, { property: "start", title: "Start Date (UTC)", type: ColumnType.text }, @@ -140,7 +140,7 @@ class MaintenenceViewComponent extends React.Component + } idProperty={'_id'}{...this.props.maintenanceEntriesActions} {...this.props.maintenanceEntriesProperties} asynchronus > @@ -160,8 +160,8 @@ class MaintenenceViewComponent extends React.Component rowData.pid ? (Running) : (Stopped) }, { property: "DeviceIp", title: "IP Adress", type: ColumnType.text }, diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx index a5b34a2dc..aaade65db 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx +++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx @@ -94,7 +94,7 @@ class MediatorServerSelectionComponent extends React.Component - { dispatch(new AllAvailableLtpsLoadedAction(null, error)); diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts index 1f53a5806..0efaaae92 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/actions/toggleActions.ts @@ -1,3 +1,21 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ + import { Action } from "../../../../framework/src/flux/action"; import { currentViewType } from "../models/toggleDataType"; @@ -12,4 +30,10 @@ export class ResetAllSubViewsAction extends Action { constructor() { super(); } +} + +export class SetFilterVisibility extends Action { + constructor(public currentView: currentViewType, public isVisible: boolean) { + super(); + } } \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx index c62698630..ca00d8214 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/adaptiveModulation.tsx @@ -29,17 +29,19 @@ import { createAdaptiveModulationProperties, createAdaptiveModulationActions } f import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils'; import { addColumnLabels } from '../utils/tableUtils'; import ToggleContainer from './toggleContainer'; -import { SetSubViewAction } from '../actions/toggleActions'; +import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions'; const mapProps = (state: IApplicationStoreState) => ({ adaptiveModulationProperties: createAdaptiveModulationProperties(state), - currentView: state.performanceHistory.subViews.adaptiveModulation, - + currentView: state.performanceHistory.subViews.adaptiveModulation.subView, + isFilterVisible: state.performanceHistory.subViews.adaptiveModulation.isFilterVisible, + existingFilter: state.performanceHistory.adaptiveModulation.filter }); const mapDisp = (dispatcher: IDispatcher) => ({ adaptiveModulationActions: createAdaptiveModulationActions(dispatcher.dispatch), setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("adaptiveModulation", value)), + toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("adaptiveModulation", value)) }, }); type AdaptiveModulationComponentProps = RouteComponentProps & Connect & { @@ -52,6 +54,11 @@ const AdaptiveModulationTable = MaterialTable as MaterialTableCtorType{ + + onToggleFilterButton = () => { + this.props.toggleFilterButton(!this.props.isFilterVisible); + } + onChange = (value: "chart" | "table") => { this.props.setSubView(value); } @@ -66,10 +73,7 @@ class AdaptiveModulationComponent extends React.Component { - const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString(); - return
{suspectIntervalFlag}
- } + property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean }]; chartPagedData.datasets.forEach(ds => { @@ -78,9 +82,9 @@ class AdaptiveModulationComponent extends React.Component - + {lineChart(chartPagedData)} - + ); diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx new file mode 100644 index 000000000..280a1dac8 --- /dev/null +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/chartFilter.tsx @@ -0,0 +1,50 @@ +import * as React from 'react'; +import { makeStyles, TextField, Typography, Select, MenuItem, FormControl, InputLabel } from '@material-ui/core'; + +const styles = makeStyles({ + filterInput: { + marginRight: "15px" + }, + filterContainer: { + marginLeft: "90px" + } +}); + +type filterProps = { isVisible: boolean, onFilterChanged: (property: string, filterTerm: string) => void, filters: any }; +//put chart visibility into redux +const ChartFilter: React.FunctionComponent = (props) => { + + //get filter from redux state (just pass da object?), onfilterchange + const classes = styles(); + + return ( + <> + { + props.isVisible && +
+ props.onFilterChanged("radioSignalId", event.target.value)} InputLabelProps={{ + shrink: true, + }} /> + props.onFilterChanged("scannerId", event.target.value)} InputLabelProps={{ + shrink: true, + }} /> + props.onFilterChanged("timeStamp", event.target.value)} InputLabelProps={{ + shrink: true, + }} /> + + Suspect Interval + + + + + } + + ) + +} + +export default ChartFilter; \ No newline at end of file diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx index 7489757f5..a8c6ed78d 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/crossPolarDiscrimination.tsx @@ -28,19 +28,22 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes'; import { createCrossPolarDiscriminationProperties, createCrossPolarDiscriminationActions } from '../handlers/crossPolarDiscriminationHandler'; import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils'; import { addColumnLabels } from '../utils/tableUtils'; -import { SetSubViewAction } from '../actions/toggleActions'; +import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions'; import ToggleContainer from './toggleContainer'; const mapProps = (state: IApplicationStoreState) => ({ crossPolarDiscriminationProperties: createCrossPolarDiscriminationProperties(state), - currentView: state.performanceHistory.subViews.CPD, + currentView: state.performanceHistory.subViews.CPD.subView, + isFilterVisible: state.performanceHistory.subViews.CPD.isFilterVisible, + existingFilter: state.performanceHistory.crossPolarDiscrimination.filter }); const mapDisp = (dispatcher: IDispatcher) => ({ crossPolarDiscriminationActions: createCrossPolarDiscriminationActions(dispatcher.dispatch), setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("CPD", value)), + toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("CPD", value)) }, }); type CrossPolarDiscriminationComponentProps = RouteComponentProps & Connect & { @@ -54,6 +57,10 @@ const CrossPolarDiscriminationTable = MaterialTable as MaterialTableCtorType{ + onToggleFilterButton = () => { + this.props.toggleFilterButton(!this.props.isFilterVisible); + } + onChange = (value: "chart" | "table") => { this.props.setSubView(value); } @@ -69,10 +76,7 @@ class CrossPolarDiscriminationComponent extends React.Component { - const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString(); - return
{suspectIntervalFlag}
- } + property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean } ]; @@ -81,9 +85,9 @@ class CrossPolarDiscriminationComponent extends React.Component - + {lineChart(chartPagedData)} - + ); diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx index 8327ec4ed..b0aebd208 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/ltpSelection.tsx @@ -17,7 +17,7 @@ */ import * as React from 'react'; -import { MenuItem, Select, FormControl } from '@material-ui/core'; +import { MenuItem, Select, FormControl, Typography } from '@material-ui/core'; import { makeStyles } from '@material-ui/core/styles'; import { LtpIds } from 'models/availableLtps'; import { Loader } from '../../../../framework/src/components/material-ui'; @@ -43,10 +43,11 @@ const useStyles = makeStyles(theme => ({ "display": "flex", "alignItems": "center", "justifyContent": "center", + flexDirection: "column" } })); -type LtpSelectionProps = { selectedNE: string, finishedLoading: boolean, selectedLtp: string, availableLtps: LtpIds[], onChangeLtp(event: React.ChangeEvent): void, selectedTimePeriod: string, onChangeTimePeriod(event: React.ChangeEvent): void }; +type LtpSelectionProps = { selectedNE: string, error?: string, finishedLoading: boolean, selectedLtp: string, availableLtps: LtpIds[], onChangeLtp(event: React.ChangeEvent): void, selectedTimePeriod: string, onChangeTimePeriod(event: React.ChangeEvent): void }; export const LtpSelection = (props: LtpSelectionProps) => { const classes = useStyles(); @@ -69,18 +70,29 @@ export const LtpSelection = (props: LtpSelectionProps) => { { - !props.finishedLoading && + !props.finishedLoading && !props.error &&

Collecting Data ...

} { - props.selectedLtp === "-1" && props.finishedLoading && + props.finishedLoading && props.error &&
-

Please select a LTP

+

Data couldn't be loaded

+ {props.error}
} + { + props.selectedLtp === "-1" && props.finishedLoading && !props.error && (props.availableLtps.length > 0 ? +
+

Please select a LTP

+
+ : +
+

No performance data found

+
) + } ) } diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx index d0caa6fd6..0a4f03273 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/performanceData.tsx @@ -28,16 +28,19 @@ import { createPerformanceDataProperties, createPerformanceDataActions } from '. import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils'; import { addColumnLabels } from '../utils/tableUtils'; import ToggleContainer from './toggleContainer'; -import { SetSubViewAction } from '../actions/toggleActions'; +import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions'; const mapProps = (state: IApplicationStoreState) => ({ performanceDataProperties: createPerformanceDataProperties(state), - currentView: state.performanceHistory.subViews.performanceDataSelection, + currentView: state.performanceHistory.subViews.performanceData.subView, + isFilterVisible: state.performanceHistory.subViews.performanceData.isFilterVisible, + existingFilter: state.performanceHistory.performanceData.filter }); const mapDisp = (dispatcher: IDispatcher) => ({ performanceDataActions: createPerformanceDataActions(dispatcher.dispatch), setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("performanceData", value)), + toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("performanceData", value)) } }); type PerformanceDataComponentProps = RouteComponentProps & Connect & { @@ -51,8 +54,8 @@ const PerformanceDataTable = MaterialTable as MaterialTableCtorType{ - onChange = (value: "chart" | "table") => { - this.props.setSubView(value); + onToggleFilterButton = () => { + this.props.toggleFilterButton(!this.props.isFilterVisible); } render(): JSX.Element { @@ -65,10 +68,7 @@ class PerformanceDataComponent extends React.Component { - const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString(); - return
{suspectIntervalFlag}
- } + property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean } ]; @@ -77,9 +77,9 @@ class PerformanceDataComponent extends React.Component - + this.props.toggleFilterButton(!this.props.isFilterVisible)} existingFilter={this.props.existingFilter} onFilterChanged={this.props.performanceDataActions.onFilterChanged} selectedValue={this.props.currentView} showFilter={this.props.isFilterVisible} onChange={this.props.setSubView}> {lineChart(chartPagedData)} - + ); diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx index 4b0a835d4..ae729306b 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/receiveLevel.tsx @@ -28,19 +28,20 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes'; import { createReceiveLevelProperties, createReceiveLevelActions } from '../handlers/receiveLevelHandler'; import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils'; import { addColumnLabels } from '../utils/tableUtils'; -import { SetSubViewAction } from '../actions/toggleActions'; +import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions'; import ToggleContainer from './toggleContainer'; const mapProps = (state: IApplicationStoreState) => ({ receiveLevelProperties: createReceiveLevelProperties(state), - currentView: state.performanceHistory.subViews.receiveLevelDataSelection, - + currentView: state.performanceHistory.subViews.receiveLevel.subView, + isFilterVisible: state.performanceHistory.subViews.receiveLevel.isFilterVisible, + existingFilter: state.performanceHistory.receiveLevel.filter }); const mapDisp = (dispatcher: IDispatcher) => ({ receiveLevelActions: createReceiveLevelActions(dispatcher.dispatch), setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("receiveLevel", value)), - + toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("receiveLevel", value)) }, }); type ReceiveLevelComponentProps = RouteComponentProps & Connect & { @@ -54,6 +55,11 @@ const ReceiveLevelTable = MaterialTable as MaterialTableCtorType{ + onToggleFilterButton = () => { + this.props.toggleFilterButton(!this.props.isFilterVisible); + } + + onChange = (value: "chart" | "table") => { this.props.setSubView(value); } @@ -68,10 +74,7 @@ class ReceiveLevelComponent extends React.Component{ { property: "scannerId", title: "Scanner ID", type: ColumnType.text }, { property: "timeStamp", title: "End Time", type: ColumnType.text }, { - property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => { - const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString(); - return
{suspectIntervalFlag}
- } + property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean } ]; @@ -81,9 +84,9 @@ class ReceiveLevelComponent extends React.Component{ return ( <> - + {lineChart(chartPagedData)} - + ); diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx index ba480d57d..00eba5fe3 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/signalToInterference.tsx @@ -28,17 +28,20 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes'; import { createSignalToInterferenceProperties, createSignalToInterferenceActions } from '../handlers/signalToInterferenceHandler'; import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils'; import { addColumnLabels } from '../utils/tableUtils'; -import { SetSubViewAction } from '../actions/toggleActions'; +import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions'; import ToggleContainer from './toggleContainer'; const mapProps = (state: IApplicationStoreState) => ({ signalToInterferenceProperties: createSignalToInterferenceProperties(state), - currentView: state.performanceHistory.subViews.SINR, + currentView: state.performanceHistory.subViews.SINR.subView, + isFilterVisible: state.performanceHistory.subViews.SINR.isFilterVisible, + existingFilter: state.performanceHistory.signalToInterference.filter }); const mapDisp = (dispatcher: IDispatcher) => ({ signalToInterferenceActions: createSignalToInterferenceActions(dispatcher.dispatch), setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("SINR", value)), + toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("SINR", value)) }, }); type SignalToInterferenceComponentProps = RouteComponentProps & Connect & { @@ -52,6 +55,10 @@ const SignalToInterferenceTable = MaterialTable as MaterialTableCtorType{ + onToggleFilterButton = () => { + this.props.toggleFilterButton(!this.props.isFilterVisible); + } + onChange = (value: "chart" | "table") => { this.props.setSubView(value); } @@ -67,10 +74,7 @@ class SignalToInterferenceComponent extends React.Component { - const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString(); - return
{suspectIntervalFlag}
- } + property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean } ]; @@ -79,9 +83,9 @@ class SignalToInterferenceComponent extends React.Component - + {lineChart(chartPagedData)} - diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx index 28f75d84c..c0d12ee47 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/temperature.tsx @@ -29,16 +29,20 @@ import { createTemperatureProperties, createTemperatureActions } from '../handle import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils'; import { addColumnLabels } from '../utils/tableUtils'; import ToggleContainer from './toggleContainer'; -import { SetSubViewAction } from '../actions/toggleActions'; +import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions'; const mapProps = (state: IApplicationStoreState) => ({ temperatureProperties: createTemperatureProperties(state), - currentView: state.performanceHistory.subViews.temperatur, + currentView: state.performanceHistory.subViews.temperatur.subView, + isFilterVisible: state.performanceHistory.subViews.temperatur.isFilterVisible, + existingFilter: state.performanceHistory.temperature.filter }); const mapDisp = (dispatcher: IDispatcher) => ({ temperatureActions: createTemperatureActions(dispatcher.dispatch), setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("Temp", value)), + toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("Temp", value)) }, + }); type TemperatureComponentProps = RouteComponentProps & Connect & { @@ -52,6 +56,11 @@ const TemperatureTable = MaterialTable as MaterialTableCtorType{ + onToggleFilterButton = () => { + this.props.toggleFilterButton(!this.props.isFilterVisible); + } + + onChange = (value: "chart" | "table") => { this.props.setSubView(value); } @@ -66,10 +75,7 @@ class TemperatureComponent extends React.Component{ { property: "scannerId", title: "Scanner ID", type: ColumnType.text }, { property: "timeStamp", title: "End Time", type: ColumnType.text }, { - property: "suspectIntervalFlag", title: "Suspect Interval", customControl: ({ rowData }) => { - const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString(); - return
{suspectIntervalFlag}
- } + property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean } ]; @@ -79,9 +85,9 @@ class TemperatureComponent extends React.Component{ return ( <> - + {lineChart(chartPagedData)} - + ); diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx index 97a2006f7..618dddfc8 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/toggleContainer.tsx @@ -23,16 +23,34 @@ import BarChartIcon from '@material-ui/icons/BarChart'; import TableChartIcon from '@material-ui/icons/TableChart'; import { makeStyles } from '@material-ui/core'; import Tooltip from '@material-ui/core/Tooltip'; +import ChartFilter from './chartFilter' +import FilterListIcon from '@material-ui/icons/FilterList'; const styles = makeStyles({ - toggleButton: { + toggleButtonContainer: { + display: "flex", alignItems: "center", justifyContent: "center", padding: "10px", + }, + subViewGroup: { + padding: "10px" + }, + filterGroup: { + marginLeft: "10px" } }); -type toggleProps = { selectedValue: string, onChange(value: string): void }; +type filterType = { + onRefresh: () => void; + onHandleRequestSort: (orderBy: string) => void; + onToggleFilter: () => void; + onFilterChanged: (property: string, filterTerm: string) => void; + onHandleChangePage: (page: number) => void; + onHandleChangeRowsPerPage: (rowsPerPage: number | null) => void; +}; + +type toggleProps = { selectedValue: string, onChange(value: string): void, showFilter: boolean, onToggleFilterButton(): void, onFilterChanged: (property: string, filterTerm: string) => void, existingFilter: any }; const ToggleContainer: React.FunctionComponent = (props) => { @@ -44,22 +62,46 @@ const ToggleContainer: React.FunctionComponent = (props) => { } }; + const handleFilterChange = (event: React.MouseEvent, newView: string) => { + props.onToggleFilterButton(); + }; + const children = React.Children.toArray(props.children); + //hide filter if visible + table + //put current name into state, let container handle stuff itelf, register for togglestate, get right via set name + return ( <> - - - - - - - - - - - - +
+ + + + + + + + + + + + + + + + + + + + + + +
+ { + props.selectedValue === "chart" && + + + } {props.selectedValue === "chart" ? children[0] : props.selectedValue === "table" && children[1]} ); diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx index 6fe66d2b5..d89aca052 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/components/transmissionPower.tsx @@ -28,17 +28,22 @@ import { IDataSet, IDataSetsObject } from '../models/chartTypes'; import { createTransmissionPowerProperties, createTransmissionPowerActions } from '../handlers/transmissionPowerHandler'; import { lineChart, sortDataByTimeStamp } from '../utils/chartUtils'; import { addColumnLabels } from '../utils/tableUtils'; -import { SetSubViewAction } from '../actions/toggleActions'; +import { SetSubViewAction, SetFilterVisibility } from '../actions/toggleActions'; import ToggleContainer from './toggleContainer'; const mapProps = (state: IApplicationStoreState) => ({ transmissionPowerProperties: createTransmissionPowerProperties(state), - currentView: state.performanceHistory.subViews.transmissionPower, + currentView: state.performanceHistory.subViews.transmissionPower.subView, + isFilterVisible: state.performanceHistory.subViews.transmissionPower.isFilterVisible, + existingFilter: state.performanceHistory.transmissionPower.filter }); const mapDisp = (dispatcher: IDispatcher) => ({ transmissionPowerActions: createTransmissionPowerActions(dispatcher.dispatch), setSubView: (value: "chart" | "table") => dispatcher.dispatch(new SetSubViewAction("transmissionPower", value)), + toggleFilterButton: (value: boolean) => { dispatcher.dispatch(new SetFilterVisibility("transmissionPower", value)) }, + + }); type TransmissionPowerComponentProps = RouteComponentProps & Connect & { @@ -52,6 +57,10 @@ const TransmissionPowerTable = MaterialTable as MaterialTableCtorType{ + onToggleFilterButton = () => { + this.props.toggleFilterButton(!this.props.isFilterVisible); + } + onChange = (value: "chart" | "table") => { this.props.setSubView(value); } @@ -67,10 +76,7 @@ class TransmissionPowerComponent extends React.Component { - const suspectIntervalFlag = rowData["suspectIntervalFlag"].toString(); - return
{suspectIntervalFlag}
- } + property: "suspectIntervalFlag", title: "Suspect Interval", type: ColumnType.boolean } ]; @@ -80,9 +86,9 @@ class TransmissionPowerComponent extends React.Component - + {lineChart(chartPagedData)} - + ); diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts index fd137fe37..4605efdb0 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/availableLtpsActionHandler.ts @@ -21,6 +21,8 @@ import { AllAvailableLtpsLoadedAction, LoadAllAvailableLtpsAction, SetInitialLoadedAction, + NoLtpsFoundAction, + ResetLtpsAction, } from '../actions/ltpAction'; import { LtpIds } from '../models/availableLtps'; @@ -29,12 +31,14 @@ export interface IAvailableLtpsState { distinctLtps: LtpIds[]; busy: boolean; loadedOnce: boolean; + error: string | undefined; } const ltpListStateInit: IAvailableLtpsState = { distinctLtps: [], busy: false, - loadedOnce: false + loadedOnce: false, + error: undefined }; export const availableLtpsActionHandler: IActionHandler = (state = ltpListStateInit, action) => { @@ -51,8 +55,16 @@ export const availableLtpsActionHandler: IActionHandler = ( ...state, distinctLtps: action.availableLtps, busy: false, + error: undefined, loadedOnce: true }; + } else if (action.error) { + state = { + ...state, + busy: false, + loadedOnce: true, + error: action.error + } } } else if (action instanceof SetInitialLoadedAction) { @@ -60,7 +72,25 @@ export const availableLtpsActionHandler: IActionHandler = ( ...state, loadedOnce: action.initialLoaded }; - } else { + } else if (action instanceof NoLtpsFoundAction) { + state = { + ...state, + busy: false, + error: undefined, + loadedOnce: true, + distinctLtps: [] + } + } else if (action instanceof ResetLtpsAction) { + state = { + ...state, + busy: false, + error: undefined, + loadedOnce: false, + distinctLtps: [] + } + } + + else { state = { ...state, busy: false diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts index e57f3860c..6b9081502 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/handlers/performanceHistoryRootHandler.ts @@ -37,8 +37,8 @@ import { IAvailableLtpsState, availableLtpsActionHandler } from './availableLtps import { PmDataInterval } from '../models/performanceDataType'; import { TimeChangeAction } from '../actions/timeChangeAction'; import { UpdateMountId } from '../actions/deviceListActions'; -import { SetSubViewAction, ResetAllSubViewsAction } from '../actions/toggleActions'; -import { SubTabType } from '../models/toggleDataType'; +import { SetSubViewAction, ResetAllSubViewsAction, SetFilterVisibility } from '../actions/toggleActions'; +import { SubTabType, currentViewType } from '../models/toggleDataType'; export interface IPerformanceHistoryStoreState { nodeId: string; @@ -81,24 +81,46 @@ const currentPMDataIntervalHandler: IActionHandler = (state = Pm return state; } +type filterableSubview = { subView: SubTabType, isFilterVisible: boolean }; +type toggleViewDataType = { currentSubView: currentViewType, performanceData: filterableSubview, receiveLevel: filterableSubview, transmissionPower: filterableSubview, adaptiveModulation: filterableSubview, temperatur: filterableSubview, SINR: filterableSubview, CPD: filterableSubview }; -type toggleViewDataType = { performanceDataSelection: SubTabType, receiveLevelDataSelection: SubTabType, transmissionPower: SubTabType, adaptiveModulation: SubTabType, temperatur: SubTabType, SINR: SubTabType, CPD: SubTabType }; - -const toogleViewDataHandler: IActionHandler = (state = { performanceDataSelection: "chart", receiveLevelDataSelection: "chart", adaptiveModulation: "chart", transmissionPower: "chart", temperatur: "chart", SINR: "chart", CPD: "chart" }, action) => { +const toogleViewDataHandler: IActionHandler = (state = { currentSubView: "performanceData", performanceData: { subView: "chart", isFilterVisible: true }, receiveLevel: { subView: "chart", isFilterVisible: true }, adaptiveModulation: { subView: "chart", isFilterVisible: true }, transmissionPower: { subView: "chart", isFilterVisible: true }, temperatur: { subView: "chart", isFilterVisible: true }, SINR: { subView: "chart", isFilterVisible: true }, CPD: { subView: "chart", isFilterVisible: true } }, action) => { if (action instanceof SetSubViewAction) { switch (action.currentView) { - case "performanceData": state = { ...state, performanceDataSelection: action.selectedTab }; break; - case "adaptiveModulation": state = { ...state, adaptiveModulation: action.selectedTab }; break; - case "receiveLevel": state = { ...state, receiveLevelDataSelection: action.selectedTab }; break; - case "transmissionPower": state = { ...state, transmissionPower: action.selectedTab }; break; - case "Temp": state = { ...state, temperatur: action.selectedTab }; break; - case "SINR": state = { ...state, SINR: action.selectedTab }; break; - case "CPD": state = { ...state, CPD: action.selectedTab }; break; + case "performanceData": state = { ...state, performanceData: { ...state.performanceData, subView: action.selectedTab } }; break; + case "adaptiveModulation": state = { ...state, adaptiveModulation: { ...state.adaptiveModulation, subView: action.selectedTab } }; break; + case "receiveLevel": state = { ...state, receiveLevel: { ...state.receiveLevel, subView: action.selectedTab } }; break; + case "transmissionPower": state = { ...state, transmissionPower: { ...state.transmissionPower, subView: action.selectedTab } }; break; + case "Temp": state = { ...state, temperatur: { ...state.temperatur, subView: action.selectedTab } }; break; + case "SINR": state = { ...state, SINR: { ...state.SINR, subView: action.selectedTab } }; break; + case "CPD": state = { ...state, CPD: { ...state.CPD, subView: action.selectedTab } }; break; + } + } + else if (action instanceof SetFilterVisibility) { + switch (action.currentView) { + case "performanceData": state = { + ...state, performanceData: { ...state.performanceData, isFilterVisible: action.isVisible } + }; break; + case "adaptiveModulation": state = { ...state, adaptiveModulation: { ...state.performanceData, isFilterVisible: action.isVisible } }; break; + case "receiveLevel": state = { ...state, receiveLevel: { ...state.receiveLevel, isFilterVisible: action.isVisible } }; break; + case "transmissionPower": state = { ...state, transmissionPower: { ...state.transmissionPower, isFilterVisible: action.isVisible } }; break; + case "Temp": state = { ...state, temperatur: { ...state.temperatur, isFilterVisible: action.isVisible } }; break; + case "SINR": state = { ...state, SINR: { ...state.SINR, isFilterVisible: action.isVisible } }; break; + case "CPD": state = { ...state, CPD: { ...state.CPD, isFilterVisible: action.isVisible } }; break; } + } else if (action instanceof ResetAllSubViewsAction) { - state = { performanceDataSelection: "chart", adaptiveModulation: "chart", receiveLevelDataSelection: "chart", transmissionPower: "chart", temperatur: "chart", SINR: "chart", CPD: "chart" } + state = { + ...state, performanceData: { ...state.performanceData, subView: "chart" }, + adaptiveModulation: { ...state.adaptiveModulation, subView: "chart" }, + receiveLevel: { ...state.receiveLevel, subView: "chart" }, + transmissionPower: { ...state.transmissionPower, subView: "chart" }, + temperatur: { ...state.temperatur, subView: "chart" }, + SINR: { ...state.SINR, subView: "chart" }, + CPD: { ...state.CPD, subView: "chart" } + } } return state; diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts b/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts index 2b03d1c2e..685859850 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/services/performanceHistoryService.ts @@ -53,7 +53,7 @@ class PerformanceService { } const result = await requestRest>(path, { method: "POST", body: JSON.stringify(convertPropertyNames({ input: query }, replaceUpperCase)) }); - return result && result.output && result.output.data.map(ne => ({ key: ne })) || null; + return result && result.output && result.output.data && result.output.data.map(ne => ({ key: ne })) || null; } diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx b/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx index 4984e80c3..4a1c654fb 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/src/views/performanceHistoryApplication.tsx @@ -39,7 +39,7 @@ import SignalToInterference from '../components/signalToInterference'; import CrossPolarDiscrimination from '../components/crossPolarDiscrimination'; import { loadAllDeviceListAsync } from '../actions/deviceListActions'; import { TimeChangeAction } from '../actions/timeChangeAction'; -import { loadDistinctLtpsbyNetworkElementAsync, SetInitialLoadedAction } from '../actions/ltpAction'; +import { loadDistinctLtpsbyNetworkElementAsync, ResetLtpsAction } from '../actions/ltpAction'; import { SetPanelAction } from '../actions/panelChangeActions'; import { createPerformanceDataPreActions, performanceDataReloadAction, createPerformanceDataActions } from '../handlers/performanceDataHandler'; import { createReceiveLevelPreActions, receiveLevelReloadAction, createReceiveLevelActions } from '../handlers/receiveLevelHandler'; @@ -69,7 +69,8 @@ const mapProps = (state: IApplicationStoreState) => ({ activePanel: state.performanceHistory.currentOpenPanel, availableLtps: state.performanceHistory.ltps.distinctLtps, networkElements: state.performanceHistory.networkElements.deviceList, - initialLoaded: state.performanceHistory.ltps.loadedOnce + initialLoaded: state.performanceHistory.ltps.loadedOnce, + error: state.performanceHistory.ltps.error }); const mapDispatcher = (dispatcher: IDispatcher) => ({ @@ -103,7 +104,7 @@ const mapDispatcher = (dispatcher: IDispatcher) => ({ changeNode: (nodeId: string) => dispatcher.dispatch((dispatch: Dispatch) => { dispatch(new NavigateToApplication("performanceHistory", nodeId)); }), - setInitialLoaded: (isLoaded: boolean) => dispatcher.dispatch((dispatch: Dispatch) => { dispatch(new SetInitialLoadedAction(isLoaded)); }), + resetLtps: () => dispatcher.dispatch((dispatch: Dispatch) => { dispatch(new ResetLtpsAction()); }), resetSubViews: () => dispatcher.dispatch(new ResetAllSubViewsAction()) }); @@ -138,7 +139,7 @@ class PerformanceHistoryComponent extends React.Component - { this.handleNetworkElementSelect(rowData.nodeId) }} columns={ [{ property: "nodeId", title: "Node Name" }] } /> @@ -232,7 +233,7 @@ class PerformanceHistoryComponent extends React.Component {this.state.showLtps && - @@ -293,6 +294,9 @@ class PerformanceHistoryComponent extends React.Component ${maven.build.timestamp} ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version}) - 41.0f8da02(20/02/20) + 46.9d666e7(20/02/28) ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version} diff --git a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx index b85319b40..a80a5a58d 100644 --- a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx @@ -105,6 +105,7 @@ export type MaterialTableComponentState = { export type TableApi = { forceRefresh?: () => Promise }; type MaterialTableComponentBaseProps = WithStyles & { + className?: string; columns: ColumnModel[]; idProperty: keyof TData | ((data: TData) => React.Key); tableId?: string; @@ -187,7 +188,7 @@ class MaterialTableComponent extends React.Component ((data as { [key: string]: any })[this.props.idProperty as any as string] as string | number) : this.props.idProperty; const toggleFilter = isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.onToggleFilter : () => { !this.props.disableFilter && this.setState({ showFilter: !showFilter }, this.update) } return ( - + 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 8ea0a93f4..464350a62 100644 --- a/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-table/tableFilter.tsx @@ -61,7 +61,7 @@ class EnhancedTableFilterComponent extends React.Component : null } - {columns.map(col => { + {columns.map((col, ind) => { const style = col.width ? { width: col.width } : {}; return ( + ? - : } + : } ); }, this)} diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/index.ts b/sdnr/wt/odlux/framework/src/components/material-ui/index.ts index e0e3fc943..096e4439d 100644 --- a/sdnr/wt/odlux/framework/src/components/material-ui/index.ts +++ b/sdnr/wt/odlux/framework/src/components/material-ui/index.ts @@ -18,5 +18,5 @@ export { ListItemLink } from './listItemLink'; export { Panel } from './panel'; export { ToggleButton, ToggleButtonClassKey } from './toggleButton'; -export { TreeView, ITreeItem, TreeViewCtorType} from './treeView'; +export { TreeView, TreeItem, TreeViewCtorType} from './treeView'; export { Loader } from './loader'; diff --git a/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx index e4eb3a794..98ee291d1 100644 --- a/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx @@ -16,33 +16,49 @@ * ============LICENSE_END========================================================================== */ import * as React from 'react'; +import { withStyles, WithStyles, createStyles, Theme } from '@material-ui/core/styles'; -import { SvgIconProps } from '@material-ui/core/SvgIcon'; import { List, ListItem, TextField, ListItemText, ListItemIcon, WithTheme, withTheme, Omit } from '@material-ui/core'; +import { SvgIconProps } from '@material-ui/core/SvgIcon'; import FileIcon from '@material-ui/icons/InsertDriveFile'; import CloseIcon from '@material-ui/icons/ExpandLess'; import OpenIcon from '@material-ui/icons/ExpandMore'; import FolderIcon from '@material-ui/icons/Folder'; -export interface ITreeItem { +const styles = (theme: Theme) => createStyles({ + root: { + padding: 0, + paddingBottom: 8, + paddingTop: 8, + }, + search: { + padding: `0px ${theme.spacing(1)}px` + } +}); + +export type TreeItem = { disabled?: boolean; icon?: React.ComponentType; + iconClass?: string; + content: string; + contentClass?: string; + children?: TreeItem[]; + value?: TData; } -type TreeViewComponentState = { +type TreeViewComponentState = { /** All indices of all expanded Items */ - expandedItems: TData[]; + expandedItems: TreeItem[]; /** The index of the active iten or undefined if no item is active. */ - activeItem: undefined | TData; + activeItem: undefined | TreeItem; /** The search term or undefined if search is corrently not active. */ searchTerm: undefined | string; } -type TreeViewComponentBaseProps = WithTheme & { - items: TData[]; - contentProperty: keyof Omit; - childrenProperty: keyof Omit; +type TreeViewComponentBaseProps = WithTheme & WithStyles & { + className?: string; + items: TreeItem[]; useFolderIcons?: boolean; enableSearchBar?: boolean; autoExpandFolder?: boolean; @@ -51,23 +67,23 @@ type TreeViewComponentBaseProps = WithTheme depthOffset?: number; } -type TreeViewComponentWithInternalStateProps = TreeViewComponentBaseProps & { - onItemClick?: (item: TData) => void; - onFolderClick?: (item: TData) => void; +type TreeViewComponentWithInternalStateProps = TreeViewComponentBaseProps & { + onItemClick?: (item: TreeItem) => void; + onFolderClick?: (item: TreeItem) => void; } -type TreeViewComponentWithExternalStateProps = TreeViewComponentBaseProps & TreeViewComponentState & { +type TreeViewComponentWithExternalStateProps = TreeViewComponentBaseProps & TreeViewComponentState & { onSearch: (searchTerm: string) => void; - onItemClick: (item: TData) => void; - onFolderClick: (item: TData) => void; + onItemClick: (item: TreeItem) => void; + onFolderClick: (item: TreeItem) => void; } -type TreeViewComponentProps = - TreeViewComponentWithInternalStateProps | - TreeViewComponentWithExternalStateProps; +type TreeViewComponentProps = + | TreeViewComponentWithInternalStateProps + | TreeViewComponentWithExternalStateProps; -function isTreeViewComponentWithExternalStateProps(props: TreeViewComponentProps): props is TreeViewComponentWithExternalStateProps { - const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps) +function isTreeViewComponentWithExternalStateProps(props: TreeViewComponentProps): props is TreeViewComponentWithExternalStateProps { + const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps) return ( propsWithExternalState.onSearch instanceof Function || propsWithExternalState.expandedItems !== undefined || @@ -76,7 +92,7 @@ function isTreeViewComponentWithExternalStateProps extends React.Component, TreeViewComponentState> { +class TreeViewComponent extends React.Component, TreeViewComponentState> { /** * Initializes a new instance. @@ -95,21 +111,11 @@ class TreeViewComponent extends React.Component +
{children} - {enableSearchBar && || null} + {enableSearchBar && || null} {this.renderItems(items, searchTerm && searchTerm.toLowerCase())} @@ -118,30 +124,30 @@ class TreeViewComponent extends React.Component { + private renderItems = (items: TreeItem[], searchTerm: string | undefined, depth: number = 1) => { return items.reduce((acc, item) => { - const children = this.props.childrenProperty && ((item as any)[this.props.childrenProperty] as TData[]); + const children = item.children; // this.props.childrenProperty && ((item as any)[this.props.childrenProperty] as TData[]); const childrenJsx = children && this.renderItems(children, searchTerm, depth + 1); const expanded = searchTerm - ? children && childrenJsx.length > 0 + ? childrenJsx && childrenJsx.length > 0 : !children ? false : this.state.expandedItems.indexOf(item) > -1; const isFolder = children !== undefined; - const itemJsx = this.renderItem(item, searchTerm, depth, isFolder, expanded); + const itemJsx = this.renderItem(item, searchTerm, depth, isFolder, expanded || false); itemJsx && acc.push(itemJsx); - if (isFolder && expanded) { + if (isFolder && expanded && childrenJsx) { acc.push(...childrenJsx); } return acc; }, [] as JSX.Element[]); } - private renderItem = (item: TData, searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean): JSX.Element | null => { + private renderItem = (item: TreeItem, searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean): JSX.Element | null => { const styles = { item: { paddingLeft: (((this.props.depthOffset || 0) + depth) * this.props.theme.spacing(3)), @@ -154,7 +160,7 @@ class TreeViewComponent extends React.Component extends React.Component{isFolder ? : }) || - (item.icon && ())} + (item.icon && ())} { // highlight search result @@ -193,10 +199,10 @@ class TreeViewComponent extends React.Component {text.substring(matchIndex + searchTermLength)} ) - : () + : () } - { // display the right icon, depending on the state + { // display the right icon, depending on the state !isFolder ? null : expanded ? () : ()} ) @@ -204,7 +210,7 @@ class TreeViewComponent extends React.Component { + private onFolderClick = (item: TreeItem) => { // toggle items with children if (this.state.searchTerm) return; const indexOfItemToToggle = this.state.expandedItems.indexOf(item); @@ -222,7 +228,7 @@ class TreeViewComponent extends React.Component { + private onItemClick = (item: TreeItem) => { // activate items without children this.setState({ activeItem: item, @@ -262,7 +268,7 @@ class TreeViewComponent extends React.Component = new () => React.Component, 'theme'>>; +export type TreeViewCtorType = new () => React.Component, 'theme'|'classes'>>; -export const TreeView = withTheme(TreeViewComponent); +export const TreeView = withTheme(withStyles(styles)(TreeViewComponent)); export default TreeView; \ No newline at end of file diff --git a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx index fee51621e..233c2fd61 100644 --- a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx +++ b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx @@ -133,6 +133,13 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di } } /> + {(false && process.env.NODE_ENV === "development") + ? <> + + } /> + + : null + } || null } diff --git a/sdnr/wt/odlux/framework/src/views/test.tsx b/sdnr/wt/odlux/framework/src/views/test.tsx index 68b189340..763b79a1f 100644 --- a/sdnr/wt/odlux/framework/src/views/test.tsx +++ b/sdnr/wt/odlux/framework/src/views/test.tsx @@ -27,7 +27,7 @@ import Typography from '@material-ui/core/Typography'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { MaterialTable, MaterialTableCtorType, ColumnType } from '../components/material-table'; -import { TreeView, ITreeItem, TreeViewCtorType } from '../components/material-ui/treeView'; +import { TreeView, TreeItem, TreeViewCtorType } from '../components/material-ui/treeView'; import { SvgIconProps } from '@material-ui/core/SvgIcon'; const styles = (theme: Theme) => createStyles({ @@ -814,30 +814,25 @@ const components = { 'counter': 'demoApp.counter' }; -class TreeDemoItem implements ITreeItem { - title: string; - children?: TreeDemoItem[]; - disabled?: boolean; - icon?: React.ComponentType; -} +type TreeDemoItem = TreeItem; const treeData: TreeDemoItem[] = [ { - title: "Erste Ebene", children: [ + content: "Erste Ebene", children: [ { - title: "Zweite Ebene", children: [ - { title: "Dritte Ebene" }, + content: "Zweite Ebene", children: [ + { content: "Dritte Ebene" }, ] }, - { title: "Zweite Ebene 2" }, + { content: "Zweite Ebene 2" }, ] }, - { title: "Erste Ebene 3" }, + { content: "Erste Ebene 3" }, ]; const SampleDataMaterialTable = MaterialTable as MaterialTableCtorType; -const SampleTree = TreeView as any as TreeViewCtorType; +const SampleTree = TreeView as any as TreeViewCtorType; const TestComponent = (props: WithComponents & WithStyles) => { @@ -867,11 +862,11 @@ const TestComponent = (props: WithComponents & WithStylesTree Demo - +
- ) + ); }; export const Test = withComponents(components)(withStyles(styles)(TestComponent)); diff --git a/sdnr/wt/odlux/package.json b/sdnr/wt/odlux/package.json index 12d18c14d..0ddc4c378 100644 --- a/sdnr/wt/odlux/package.json +++ b/sdnr/wt/odlux/package.json @@ -15,8 +15,8 @@ "@fortawesome/free-solid-svg-icons": "5.6.3", "@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", + "@material-ui/icons": "4.5.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", @@ -29,10 +29,9 @@ "@types/x2js": "3.1.0", "classnames": "2.2.6", "csstype": "2.6.8", + "jss": "10.0.3", "jquery": "3.3.1", "jsonwebtoken": "8.3.0", - "jss": "10.0.3", - "lerna": "3.13.1", "notistack": "0.9.6", "prop-types": "15.7.2", "react": "16.12.0", @@ -82,4 +81,4 @@ "webpack-cli": "3.2.1", "webpack-dev-server": "3.1.14" } -} +} \ No newline at end of file -- cgit 1.2.3-korg