summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAijana Schumann <aijana.schumann@highstreet-technologies.com>2020-03-13 10:39:11 +0100
committerAijana Schumann <aijana.schumann@highstreet-technologies.com>2020-03-13 10:39:11 +0100
commit05da65b2d01a75404059d7526b4cbb868f631dd7 (patch)
tree5a4a77ffd32c2a81567279c58c361344f52bb476
parent25cb54c517caacafc76534b8972fa8df86a80dbf (diff)
Fix odlux bugs
Fix help and about app not scrollable Fix filter hiding and showing without user interaction and default sort in all tables Issue-ID: SDNC-1117 Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com> Change-Id: I5c6ff86c73a3b222a8d9022125454788496f6399
-rw-r--r--sdnr/wt/data-provider/provider/pom.xml2
-rw-r--r--sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx9
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx12
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx9
-rw-r--r--sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx4
-rw-r--r--sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx11
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/actions/partialUpdatesAction.ts25
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts24
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx20
-rw-r--r--sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx43
-rw-r--r--sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx18
-rw-r--r--sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx15
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx2
-rw-r--r--sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx10
-rw-r--r--sdnr/wt/odlux/framework/pom.xml2
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/index.tsx6
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-table/utilities.ts27
-rw-r--r--sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx120
-rw-r--r--sdnr/wt/odlux/framework/src/components/navigationMenu.tsx32
-rw-r--r--sdnr/wt/odlux/framework/src/index.dev.html6
-rw-r--r--sdnr/wt/odlux/framework/src/views/about.tsx14
-rw-r--r--sdnr/wt/odlux/framework/src/views/frame.tsx1
22 files changed, 320 insertions, 92 deletions
diff --git a/sdnr/wt/data-provider/provider/pom.xml b/sdnr/wt/data-provider/provider/pom.xml
index fae95d27a..dd2e03a2a 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>46.9d666e7(20/02/28)</odlux.buildno>
+ <odlux.buildno>50.53aa73a(20/03/12)</odlux.buildno>
</properties>
<dependencies>
diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
index c153ed5a1..503133b0f 100644
--- a/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
+++ b/sdnr/wt/odlux/apps/configurationApp/src/views/networkElementSelector.tsx
@@ -39,10 +39,17 @@ const ConnectedElementTable = MaterialTable as MaterialTableCtorType<NetworkElem
type NetworkElementSelectorComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDispatch>;
+let initialSorted = false;
+
class NetworkElementSelectorComponent extends React.Component<NetworkElementSelectorComponentProps> {
componentDidMount() {
- this.props.connectedNetworkElementsActions.onRefresh();
+
+ if (!initialSorted) {
+ initialSorted = true;
+ this.props.connectedNetworkElementsActions.onHandleRequestSort("node-id");
+ } else
+ this.props.connectedNetworkElementsActions.onRefresh();
}
render() {
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
index ad7b247b0..96f6c8a6b 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/connectionStatusLog.tsx
@@ -35,6 +35,9 @@ const ConnectionStatusTable = MaterialTable as MaterialTableCtorType<NetworkElem
type ConnectionStatusLogComponentProps = Connect<typeof mapProps, typeof mapDispatch>;
+let initialSorted = false;
+
+
class ConnectionStatusLogComponent extends React.Component<ConnectionStatusLogComponentProps> {
render(): JSX.Element {
return (
@@ -46,6 +49,15 @@ class ConnectionStatusLogComponent extends React.Component<ConnectionStatusLogCo
</ConnectionStatusTable>
);
};
+
+ componentDidMount() {
+ if (!initialSorted) {
+ initialSorted = true;
+ this.props.connectionStatusLogActions.onHandleExplicitRequestSort("timestamp", "desc");
+ } else {
+ this.props.connectionStatusLogActions.onRefresh();
+ }
+ }
}
export const ConnectionStatusLog = connect(mapProps, mapDispatch)(ConnectionStatusLogComponent);
diff --git a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
index d50a81ed5..53e10481a 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/components/networkElements.tsx
@@ -83,7 +83,7 @@ type NetworkElementsListComponentState = {
}
const emptyRequireNetworkElement: NetworkElementConnection = { id: "", nodeId: "", host: "", port: 0, status: "Disconnected", isRequired: false };
-
+let initialSorted = false;
const NetworkElementTable = MaterialTable as MaterialTableCtorType<NetworkElementConnection>;
export class NetworkElementsListComponent extends React.Component<NetworkElementsListComponentProps, NetworkElementsListComponentState> {
@@ -173,7 +173,12 @@ export class NetworkElementsListComponent extends React.Component<NetworkElement
};
public componentDidMount() {
- this.props.networkElementsActions.onRefresh();
+ if (!initialSorted) {
+ initialSorted = true;
+ this.props.networkElementsActions.onHandleRequestSort("node-id");
+ } else {
+ this.props.networkElementsActions.onRefresh();
+ }
}
private onOpenAddNetworkElementDialog = (event: React.MouseEvent<HTMLElement>, element: NetworkElementConnection) => {
diff --git a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
index a96d3d635..a7feae923 100644
--- a/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
+++ b/sdnr/wt/odlux/apps/connectApp/src/views/connectView.tsx
@@ -61,8 +61,8 @@ class ConnectApplicationComponent extends React.Component<ConnectApplicationComp
if (this.props.panelId === null) { //don't change tabs, if one is selected already
this.onTogglePanel("NetworkElements");
}
- this.props.networkElementsActions.onToggleFilter();
- this.props.connectionStatusLogActions.onToggleFilter();
+ //this.props.networkElementsActions.onToggleFilter();
+ //this.props.connectionStatusLogActions.onToggleFilter();
}
public componentDidUpdate = async () => {
diff --git a/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx b/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx
index 5993bb5c4..aa9027206 100644
--- a/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx
+++ b/sdnr/wt/odlux/apps/eventLogApp/src/views/eventLog.tsx
@@ -35,6 +35,8 @@ const mapDispatch = (dispatcher: IDispatcher) => ({
eventLogActions: createEventLogActions(dispatcher.dispatch)
});
+let initalSorted = false;
+
class EventLogComponent extends React.Component<Connect<typeof mapProps, typeof mapDispatch>> {
render() {
return <EventLogTable stickyHeader title="Event Log" idProperty="_id" columns={[
@@ -50,8 +52,13 @@ class EventLogComponent extends React.Component<Connect<typeof mapProps, typeof
}
componentDidMount() {
- this.props.eventLogActions.onToggleFilter();
- this.props.eventLogActions.onHandleRequestSort("node-id");
+
+ if (!initalSorted) {
+ initalSorted = true;
+ this.props.eventLogActions.onHandleExplicitRequestSort("timestamp", "desc");
+ } else {
+ this.props.eventLogActions.onRefresh();
+ }
}
}
diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/partialUpdatesAction.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/partialUpdatesAction.ts
new file mode 100644
index 000000000..198976796
--- /dev/null
+++ b/sdnr/wt/odlux/apps/faultApp/src/actions/partialUpdatesAction.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==========================================================================
+ */
+
+import { Action } from "../../../../framework/src/flux/action";
+
+export class SetPartialUpdatesAction extends Action {
+ constructor(public isActive: boolean) {
+ super();
+ }
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
index a5cf928fc..e03d2b560 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
+++ b/sdnr/wt/odlux/apps/faultApp/src/handlers/faultAppRootHandler.ts
@@ -26,26 +26,31 @@ import { IActionHandler } from '../../../../framework/src/flux/action';
import { IFaultNotifications, faultNotificationsHandler } from './notificationsHandler';
import { ICurrentProblemsState, currentProblemsActionHandler } from './currentProblemsHandler';
import { IAlarmLogEntriesState, alarmLogEntriesActionHandler } from './alarmLogEntriesHandler';
-import { SetPanelAction, RememberCurrentPanelAction } from '../actions/panelChangeActions';
+import { SetPanelAction } from '../actions/panelChangeActions';
import { IFaultStatus, faultStatusHandler } from './faultStatusHandler';
import { stuckAlarmHandler } from './clearStuckAlarmsHandler';
import { PanelId } from 'models/panelId';
+import { SetPartialUpdatesAction } from '../actions/partialUpdatesAction';
export interface IFaultAppStoreState {
currentProblems: ICurrentProblemsState;
faultNotifications: IFaultNotifications;
alarmLogEntries: IAlarmLogEntriesState;
- currentOpenPanel: ICurrentOpenPanelState;
+ currentOpenPanel: PanelId | null;
faultStatus: IFaultStatus;
+ listenForPartialUpdates: boolean;
}
-type ICurrentOpenPanelState = { openPanel: string | null, savedPanel: PanelId | null };
-const panelInitState = { openPanel: null, savedPanel: null };
-const currentOpenPanelHandler: IActionHandler<ICurrentOpenPanelState> = (state = panelInitState, action) => {
+const currentOpenPanelHandler: IActionHandler<PanelId | null> = (state = null, action) => {
if (action instanceof SetPanelAction) {
- state = { ...state, openPanel: action.panelId };
- } else if (action instanceof RememberCurrentPanelAction) {
- state = { ...state, savedPanel: action.panelId };
+ state = action.panelId;
+ }
+ return state;
+}
+
+const arePartialUpdatesActiveHandler: IActionHandler<boolean> = (state = false, action) => {
+ if (action instanceof SetPartialUpdatesAction) {
+ state = action.isActive;
}
return state;
}
@@ -62,7 +67,8 @@ const actionHandlers = {
alarmLogEntries: alarmLogEntriesActionHandler,
currentOpenPanel: currentOpenPanelHandler,
faultStatus: faultStatusHandler,
- stuckAlarms: stuckAlarmHandler
+ stuckAlarms: stuckAlarmHandler,
+ listenForPartialUpdates: arePartialUpdatesActiveHandler
};
export const faultAppRootHandler = combineActionHandler<IFaultAppStoreState>(actionHandlers);
diff --git a/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
index 666667e40..2056976d9 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/pluginFault.tsx
@@ -62,8 +62,12 @@ const FaultApplicationRouteAdapter = connect(mapProps, mapDisp)((props: RouteCom
if (currentMountId) {
props.setCurrentPanel("CurrentProblem");
props.currentProblemsActions.onFilterChanged("nodeId", currentMountId);
- props.currentProblemsProperties.showFilter; // || (props.currentProblemsActions.onToggleFilter());
- props.currentProblemsActions.onRefresh();
+ if (!props.currentProblemsProperties.showFilter) {
+ props.currentProblemsActions.onToggleFilter(false);
+ props.currentProblemsActions.onRefresh();
+ }
+ else
+ props.currentProblemsActions.onRefresh();
}
});
}
@@ -95,11 +99,13 @@ export function register() {
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);
+ // reload fault data if the view is displayed
+ if (store.state.fault.listenForPartialUpdates) {
+ if (store.state.fault.currentOpenPanel === "AlarmLog") {
+ store.dispatch(alarmLogEntriesReloadAction);
+ } else if (store.state.fault.currentOpenPanel === "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 ed395d2e4..10721549c 100644
--- a/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
+++ b/sdnr/wt/odlux/apps/faultApp/src/views/faultApplication.tsx
@@ -33,14 +33,14 @@ import { PanelId } from '../models/panelId';
import { createCurrentProblemsProperties, createCurrentProblemsActions, currentProblemsReloadAction } from '../handlers/currentProblemsHandler';
import { createAlarmLogEntriesProperties, createAlarmLogEntriesActions, alarmLogEntriesReloadAction } from '../handlers/alarmLogEntriesHandler';
-import { setPanelAction, RememberCurrentPanelAction } from '../actions/panelChangeActions';
+import { setPanelAction } 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';
+import { SetPartialUpdatesAction } from '../actions/partialUpdatesAction';
const mapProps = (state: IApplicationStoreState) => ({
- panelId: state.fault.currentOpenPanel.openPanel,
- savedPanel: state.fault.currentOpenPanel.savedPanel,
+ panelId: state.fault.currentOpenPanel,
currentProblemsProperties: createCurrentProblemsProperties(state),
faultNotifications: state.fault.faultNotifications,
alarmLogEntriesProperties: createAlarmLogEntriesProperties(state)
@@ -54,7 +54,7 @@ const mapDisp = (dispatcher: IDispatcher) => ({
switchActivePanel: (panelId: PanelId) => {
dispatcher.dispatch(setPanelAction(panelId));
},
- rememberCurrentPanel: (panelId: PanelId) => dispatcher.dispatch(new RememberCurrentPanelAction(panelId))
+ setPartialUpdates: (active: boolean) => dispatcher.dispatch(new SetPartialUpdatesAction(active))
});
type FaultApplicationComponentProps = RouteComponentProps & Connect<typeof mapProps, typeof mapDisp>;
@@ -68,6 +68,8 @@ type FaultApplicationState = {
const FaultTable = MaterialTable as MaterialTableCtorType<Fault>;
const FaultAlarmNotificationTable = MaterialTable as MaterialTableCtorType<FaultAlarmNotification>;
+let currentProblemsInitalSorted = false;
+let alarmLogInitialSorted = false;
class FaultApplicationComponent extends React.Component<FaultApplicationComponentProps, FaultApplicationState>{
@@ -97,10 +99,20 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen
this.props.switchActivePanel(nextActivePanel);
switch (nextActivePanel) {
case 'CurrentProblem':
- this.props.reloadCurrentProblems();
+ if (!currentProblemsInitalSorted) {
+ currentProblemsInitalSorted = true;
+ this.props.currentProblemsActions.onHandleExplicitRequestSort("timestamp", "desc");
+ } else {
+ this.props.reloadCurrentProblems();
+ }
break;
case 'AlarmLog':
- this.props.reloadAlarmLogEntries();
+ if (!alarmLogInitialSorted) {
+ alarmLogInitialSorted = true;
+ this.props.alarmLogEntriesActions.onHandleExplicitRequestSort("timestamp", "desc");
+ } else {
+ this.props.reloadAlarmLogEntries();
+ }
break;
case 'AlarmNotifications':
case null:
@@ -177,25 +189,16 @@ class FaultApplicationComponent extends React.Component<FaultApplicationComponen
};
componentWillUnmount() {
- if (this.props.panelId) {
- this.props.rememberCurrentPanel(this.props.panelId as PanelId);
- this.props.switchActivePanel(null);
- }
+ this.props.setPartialUpdates(false);
}
public componentDidMount() {
-
- if (this.props.panelId === null && this.props.savedPanel === null) { //set default tab if none is set
+ if (this.props.panelId === null) { //set default tab if none is set
this.onToggleTabs("CurrentProblem");
- } else // load saved tab if possible
- if (this.props.panelId === null && this.props.savedPanel !== null) {
- this.onToggleTabs(this.props.savedPanel);
- this.props.rememberCurrentPanel(null);
- }
-
- this.props.alarmLogEntriesActions.onToggleFilter();
- this.props.currentProblemsActions.onToggleFilter();
+ }
+ this.props.setPartialUpdates(true);
}
+
private renderIcon = (props: { rowData: Fault | FaultAlarmNotification }) => {
return (
<FontAwesomeIcon icon={faExclamationTriangle} />
diff --git a/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx b/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx
index b4de26d50..eab44b4ca 100644
--- a/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx
+++ b/sdnr/wt/odlux/apps/helpApp/src/views/helpApplication.tsx
@@ -32,6 +32,18 @@ const mapProps = (state: IApplicationStoreState) => ({
currentPath: state.help.currentPath
});
+const containerStyle = {
+ overflow: "auto",
+ height: "100%",
+ width: "100%"
+};
+
+const styles = {
+ maxWidth: "960px",
+ margin: "1.5em auto",
+
+};
+
type HelpApplicationComponentProps = Connect<typeof mapProps>;
class HelpApplicationComponent extends React.Component<HelpApplicationComponentProps> {
@@ -58,8 +70,10 @@ class HelpApplicationComponent extends React.Component<HelpApplicationComponentP
render(): JSX.Element {
return this.props.content ? (
- <Markdown text={this.props.content} markedOptions={{ renderer: this.renderer }} className="markdown-body"
- style={{ maxWidth: "960px", margin: "1.5em auto" }} />
+ <div style={containerStyle}>
+ <Markdown text={this.props.content} markedOptions={{ renderer: this.renderer }} className="markdown-body"
+ style={styles} />
+ </div>
) : (<h2>Loading ...</h2>)
}
diff --git a/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx b/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx
index 350bac221..f087ed2e4 100644
--- a/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx
+++ b/sdnr/wt/odlux/apps/maintenanceApp/src/views/maintenenceView.tsx
@@ -81,7 +81,9 @@ type MaintenenceViewComponentProps = Connect<typeof mapProps, typeof mapDispatch
type MaintenenceViewComponentState = {
maintenenceEntryToEdit: MaintenenceEntry;
maintenenceEntryEditorMode: EditMaintenenceEntryDialogMode;
-}
+};
+
+let initialSorted = false;
class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentProps, MaintenenceViewComponentState> {
@@ -148,8 +150,15 @@ class MaintenenceViewComponent extends React.Component<MaintenenceViewComponentP
}
public componentDidMount() {
- this.props.maintenanceEntriesActions.onRefresh();
- this.props.onLoadMaintenanceEntries();
+
+ if (!initialSorted) {
+ initialSorted = true;
+ this.props.maintenanceEntriesActions.onHandleRequestSort("node-id");
+ } else {
+ this.props.onLoadMaintenanceEntries();
+ }
+
+
}
private onOpenPlus1hEditMaintenenceEntryDialog = (event: React.MouseEvent<HTMLElement>, entry: MaintenenceEntry) => {
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
index d422a0c3b..f96223297 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx
@@ -161,7 +161,7 @@ class MediatorApplicationComponent extends React.Component<MediatorApplicationCo
this.props.isReachable ?
- <MediatorServerConfigurationsTable stickyHeader title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[
+ <MediatorServerConfigurationsTable defaultSortColumn={"Name"} defaultSortOrder="asc" stickyHeader title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[
{ property: "Name", title: "Mediator", type: ColumnType.text },
{ property: "Status", title: "Status", type: ColumnType.custom, customControl: ({ rowData }) => rowData.pid ? (<span>Running</span>) : (<span>Stopped</span>) },
{ property: "DeviceIp", title: "IP Adress", type: ColumnType.text },
diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
index aaade65db..c16906ad0 100644
--- a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
+++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx
@@ -70,6 +70,8 @@ type MediatorServerSelectionComponentState = {
mediatorServerEditorMode: EditMediatorServerDialogMode
}
+let initialSorted = false;
+
class MediatorServerSelectionComponent extends React.Component<MediatorServerSelectionComponentProps, MediatorServerSelectionComponentState> {
constructor(props: MediatorServerSelectionComponentProps) {
@@ -116,7 +118,13 @@ class MediatorServerSelectionComponent extends React.Component<MediatorServerSel
}
public componentDidMount() {
- this.props.mediatorServersActions.onToggleFilter();
+
+ if (!initialSorted) {
+ initialSorted = true;
+ this.props.mediatorServersActions.onHandleRequestSort("name");
+ } else {
+ this.props.mediatorServersActions.onRefresh();
+ }
}
private onSelectMediatorServer = (event: React.MouseEvent<HTMLElement>, server: MediatorServer) => {
diff --git a/sdnr/wt/odlux/framework/pom.xml b/sdnr/wt/odlux/framework/pom.xml
index f9b76a0ec..5c7f846f0 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>46.9d666e7(20/02/28)</buildno>
+ <buildno>50.53aa73a(20/03/12)</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/index.tsx b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
index a80a5a58d..3dfbe0b91 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-table/index.tsx
@@ -111,6 +111,8 @@ type MaterialTableComponentBaseProps<TData> = WithStyles<typeof styles> & {
tableId?: string;
title?: string;
stickyHeader?: boolean;
+ defaultSortOrder?: 'asc' | 'desc';
+ defaultSortColumn?: keyof TData;
enableSelection?: boolean;
disableSorting?: boolean;
disableFilter?: boolean;
@@ -164,8 +166,8 @@ class MaterialTableComponent<TData extends {} = {}> extends React.Component<Mate
filter: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.filter || {} : {},
showFilter: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.showFilter : false,
loading: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.loading : false,
- order: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.order : 'asc',
- orderBy: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.orderBy : null,
+ order: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.order : this.props.defaultSortOrder || 'asc',
+ orderBy: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.orderBy : this.props.defaultSortColumn || null,
selected: isMaterialTableComponentPropsWithRowsAndRequestData(this.props) ? this.props.selected : null,
rows: isMaterialTableComponentPropsWithRows(this.props) && this.props.rows.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage) || [],
total: isMaterialTableComponentPropsWithRows(this.props) && this.props.rows.length || 0,
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts b/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
index 74682cd95..07ffe2ff5 100644
--- a/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
+++ b/sdnr/wt/odlux/framework/src/components/material-table/utilities.ts
@@ -49,6 +49,12 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
}
}
+ class RequestExplicitSortAction extends TableAction {
+ constructor(public propertyName: string, public sortOrder: "asc" | "desc") {
+ super();
+ }
+ }
+
class SetSelectedAction extends TableAction {
constructor(public selected: TData[] | null) {
super();
@@ -136,7 +142,15 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
orderBy: state.orderBy === action.orderBy && state.order === 'desc' ? null : action.orderBy,
order: state.orderBy === action.orderBy && state.order === 'asc' ? 'desc' : 'asc',
}
- } else if (action instanceof SetShowFilterAction) {
+ } else if (action instanceof RequestExplicitSortAction) {
+ state = {
+ ...state,
+ loading: true,
+ orderBy: action.propertyName,
+ order: action.sortOrder
+ }
+ }
+ else if (action instanceof SetShowFilterAction) {
state = {
...state,
loading: true,
@@ -239,11 +253,18 @@ export function createExternal<TData>(callback: DataCallback<TData>, selectState
(!skipRefresh) && dispatch(reloadAction);
});
},
- onToggleFilter: () => {
+ onHandleExplicitRequestSort: (property: string, sortOrder: "asc" | "desc") => {
+ dispatch((dispatch: Dispatch) => {
+ dispatch(new RequestExplicitSortAction(property, sortOrder));
+ (!skipRefresh) && dispatch(reloadAction);
+ });
+ },
+ onToggleFilter: (refresh?: boolean) => {
dispatch((dispatch: Dispatch, getAppState: () => IApplicationStoreState) => {
const { showFilter } = selectState(getAppState());
dispatch(new SetShowFilterAction(!showFilter));
- (!skipRefresh) && dispatch(reloadAction);
+ if (!skipRefresh && (refresh === undefined || refresh))
+ dispatch(reloadAction);
});
},
onFilterChanged: (property: string, filterTerm: string) => {
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 98ee291d1..1bb49367c 100644
--- a/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
+++ b/sdnr/wt/odlux/framework/src/components/material-ui/treeView.tsx
@@ -37,6 +37,11 @@ const styles = (theme: Theme) => createStyles({
}
});
+export enum SearchMode {
+ OnKeyDown = 1,
+ OnEnter =2
+}
+
export type TreeItem<TData = { }> = {
disabled?: boolean;
icon?: React.ComponentType<SvgIconProps>;
@@ -47,13 +52,19 @@ export type TreeItem<TData = { }> = {
value?: TData;
}
+export type ExternalTreeItem<TData = {}> = TreeItem<TData> & {
+ isMatch?: boolean;
+}
+
+
type TreeViewComponentState<TData = { }> = {
/** All indices of all expanded Items */
- expandedItems: TreeItem<TData>[];
+ expandedItems: ExternalTreeItem<TData>[];
/** The index of the active iten or undefined if no item is active. */
- activeItem: undefined | TreeItem<TData>;
+ activeItem?: ExternalTreeItem<TData>;
/** The search term or undefined if search is corrently not active. */
- searchTerm: undefined | string;
+ searchTerm?: string;
+ searchTermValue?: string;
}
type TreeViewComponentBaseProps<TData = {}> = WithTheme & WithStyles<typeof styles> & {
@@ -65,6 +76,7 @@ type TreeViewComponentBaseProps<TData = {}> = WithTheme & WithStyles<typeof styl
style?: React.CSSProperties;
itemHeight?: number;
depthOffset?: number;
+ searchMode?: SearchMode;
}
type TreeViewComponentWithInternalStateProps<TData = { }> = TreeViewComponentBaseProps<TData> & {
@@ -72,7 +84,17 @@ type TreeViewComponentWithInternalStateProps<TData = { }> = TreeViewComponentBas
onFolderClick?: (item: TreeItem<TData>) => void;
}
-type TreeViewComponentWithExternalStateProps<TData = { }> = TreeViewComponentBaseProps<TData> & TreeViewComponentState<TData> & {
+type TreeViewComponentWithExternalSearchProps<TData = {}> = TreeViewComponentBaseProps<TData> & {
+ items: ExternalTreeItem<TData>[];
+ searchTerm: string;
+ onSearch: (searchTerm: string) => void;
+ onItemClick?: (item: TreeItem<TData>) => void;
+ onFolderClick?: (item: TreeItem<TData>) => void;
+}
+
+type TreeViewComponentWithExternalStateProps<TData = {}> = TreeViewComponentBaseProps<TData> & TreeViewComponentState<TData> & {
+ items: ExternalTreeItem<TData>[];
+ searchTerm: string;
onSearch: (searchTerm: string) => void;
onItemClick: (item: TreeItem<TData>) => void;
onFolderClick: (item: TreeItem<TData>) => void;
@@ -80,14 +102,25 @@ type TreeViewComponentWithExternalStateProps<TData = { }> = TreeViewComponentBas
type TreeViewComponentProps<TData = { }> =
| TreeViewComponentWithInternalStateProps<TData>
+ | TreeViewComponentWithExternalSearchProps<TData>
| TreeViewComponentWithExternalStateProps<TData>;
+function isTreeViewComponentWithExternalSearchProps(props: TreeViewComponentProps): props is TreeViewComponentWithExternalSearchProps {
+ const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps)
+ return (
+ propsWithExternalState.onSearch instanceof Function &&
+ propsWithExternalState.onFolderClick === undefined &&
+ propsWithExternalState.expandedItems === undefined &&
+ propsWithExternalState.searchTerm !== undefined
+ );
+}
+
function isTreeViewComponentWithExternalStateProps(props: TreeViewComponentProps): props is TreeViewComponentWithExternalStateProps {
const propsWithExternalState = (props as TreeViewComponentWithExternalStateProps)
return (
- propsWithExternalState.onSearch instanceof Function ||
- propsWithExternalState.expandedItems !== undefined ||
- propsWithExternalState.activeItem !== undefined ||
+ propsWithExternalState.onSearch instanceof Function &&
+ propsWithExternalState.onFolderClick instanceof Function &&
+ propsWithExternalState.expandedItems !== undefined &&
propsWithExternalState.searchTerm !== undefined
);
}
@@ -103,19 +136,20 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
this.state = {
expandedItems: [],
activeItem: undefined,
- searchTerm: undefined
+ searchTerm: undefined,
+ searchTermValue: undefined
};
}
render(): JSX.Element {
this.itemIndex = 0;
- const { searchTerm } = this.state;
+ const { searchTerm , searchTermValue} = this.state;
const { children, items, enableSearchBar } = this.props;
return (
<div className={this.props.className ? `${this.props.classes.root} ${this.props.className}` : this.props.classes.root} style={this.props.style}>
{children}
- {enableSearchBar && <TextField label={"Search"} fullWidth={true} className={ this.props.classes.search } value={searchTerm} onChange={this.onChangeSearchText} /> || null}
+ {enableSearchBar && <TextField label={"Search"} fullWidth={true} className={this.props.classes.search} value={searchTermValue} onKeyDown={this.onSearchKeyDown} onChange={this.onChangeSearchText} /> || null}
<List>
{this.renderItems(items, searchTerm && searchTerm.toLowerCase())}
</List>
@@ -124,20 +158,21 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
}
private itemIndex: number = 0;
- private renderItems = (items: TreeItem<TData>[], searchTerm: string | undefined, depth: number = 1) => {
+ private renderItems = (items: TreeItem<TData>[], searchTerm: string | undefined, depth: number = 1, forceRender: boolean = true) => {
+
return items.reduce((acc, item) => {
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 childrenJsx = children && this.renderItems(children, searchTerm, depth + 1, this.state.expandedItems.indexOf(item) > -1);
- const expanded = searchTerm
+ const expanded = !isTreeViewComponentWithExternalStateProps(this.props) && searchTerm
? 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 || false);
+ const itemJsx = this.renderItem(item, searchTerm, depth, isFolder, expanded || false, forceRender);
itemJsx && acc.push(itemJsx);
if (isFolder && expanded && childrenJsx) {
@@ -147,7 +182,7 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
}, [] as JSX.Element[]);
}
- private renderItem = (item: TreeItem<TData>, searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean): JSX.Element | null => {
+ private renderItem = (item: ExternalTreeItem<TData>, searchTerm: string | undefined, depth: number, isFolder: boolean, expanded: boolean, forceRender: boolean): JSX.Element | null => {
const styles = {
item: {
paddingLeft: (((this.props.depthOffset || 0) + depth) * this.props.theme.spacing(3)),
@@ -175,7 +210,7 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
}
};
- return ((searchTerm && (matchIndex > -1 || expanded) || !searchTerm)
+ return ((searchTerm && (matchIndex > -1 || expanded || (!isTreeViewComponentWithExternalStateProps(this.props) && item.isMatch || depth === 1)) || !searchTerm || forceRender)
? (
<ListItem key={`tree-list-${this.itemIndex++}`} style={styles.item} onClick={handleClickCreator(false)} button >
@@ -186,7 +221,7 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
{ // highlight search result
matchIndex > -1
- ? (<span>
+ ? <ListItemText className={item.contentClass} primary={(<span>
{text.substring(0, matchIndex)}
<span
style={{
@@ -198,8 +233,15 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
{text.substring(matchIndex, matchIndex + searchTermLength)}
</span>
{text.substring(matchIndex + searchTermLength)}
- </span>)
- : (<ListItemText className={ item.contentClass } primary={text} />)
+ </span>)} />
+ : <ListItemText className={item.contentClass} primary={(
+ <span style={item.isMatch ? {
+ display: 'inline-block',
+ backgroundColor: 'rgba(255,235,59,0.5)',
+ padding: '3px',
+ } : undefined}>
+ {text} </span>
+ )} />
}
{ // display the right icon, depending on the state
@@ -235,16 +277,39 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
});
};
+ private onSearchKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
+ const enterMode = this.props.searchMode === SearchMode.OnEnter;
+
+ if (enterMode && event.keyCode === 13) {
+ event.preventDefault();
+ event.stopPropagation();
+
+ enterMode && this.setState({
+ searchTerm: this.state.searchTermValue
+ });
+
+ if (isTreeViewComponentWithExternalSearchProps(this.props) || isTreeViewComponentWithExternalStateProps(this.props)) {
+ this.props.onSearch(this.state.searchTermValue || "");
+ }
+ }
+ }
+
private onChangeSearchText = (event: React.ChangeEvent<HTMLInputElement>) => {
event.preventDefault();
event.stopPropagation();
- if (isTreeViewComponentWithExternalStateProps(this.props)) {
- this.props.onSearch(event.target.value)
- } else {
- this.setState({
- searchTerm: event.target.value
- });
+ const keyDownMode = (!this.props.searchMode || this.props.searchMode === SearchMode.OnKeyDown);
+
+ this.setState(keyDownMode
+ ? {
+ searchTerm: event.target.value,
+ searchTermValue: event.target.value,
+ } as any : {
+ searchTermValue: event.target.value,
+ }) as any;
+
+ if ((isTreeViewComponentWithExternalSearchProps(this.props) || isTreeViewComponentWithExternalStateProps(this.props)) && keyDownMode) {
+ this.props.onSearch(event.target.value);
}
};
@@ -256,6 +321,11 @@ class TreeViewComponent<TData = { }> extends React.Component<TreeViewComponentPr
activeItem: props.activeItem,
searchTerm: props.searchTerm
};
+ } else if (isTreeViewComponentWithExternalSearchProps(props)) {
+ return {
+ ...state,
+ searchTerm: props.searchTerm,
+ };
}
return state;
}
diff --git a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
index 233c2fd61..620abd708 100644
--- a/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
+++ b/sdnr/wt/odlux/framework/src/components/navigationMenu.tsx
@@ -29,18 +29,22 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import ListItemLink from '../components/material-ui/listItemLink';
-import connect, { Connect, IDispatcher } from '../flux/connect';
+import connect, { Connect } from '../flux/connect';
import { MenuAction } from '../actions/menuAction';
import * as classNames from 'classnames';
+
const drawerWidth = 240;
+const extraLinks = (window as any)._odluxExtraLinks as [string, string][];
+
const styles = (theme: Theme) => createStyles({
drawerPaper: {
position: 'relative',
width: drawerWidth,
},
toolbar: theme.mixins.toolbar as any,
+
drawerOpen: {
width: drawerWidth,
transition: theme.transitions.create('width', {
@@ -58,7 +62,24 @@ const styles = (theme: Theme) => createStyles({
[theme.breakpoints.up('sm')]: {
width: theme.spacing(9) + 1,
},
- }
+ },
+ drawer: {
+
+ },
+ menu: {
+ flex: "1 0 0%",
+ },
+ optLinks: {
+ borderTop: "2px solid #cfcfcf",
+ display: "flex",
+ flexDirection: "row",
+ flexWrap: "wrap",
+ justifyContent: "space-around"
+ },
+ link: {
+ margin: theme.spacing(1)+1,
+ fontSize: theme.typography.fontSize-2,
+ },
});
const tabletWidthBreakpoint = 768;
@@ -103,7 +124,7 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di
<Drawer
variant="permanent"
className={
- classNames({
+ classNames(classes.drawer, {
[classes.drawerOpen]: isOpen,
[classes.drawerClose]: !isOpen
})
@@ -115,7 +136,7 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di
{user && user.isValid && <>
<div className={classes.toolbar} />
{ /* https://fiffty.github.io/react-treeview-mui/ */}
- <List component="nav">
+ <List className={classes.menu} component="nav">
<ListItemLink exact to="/" primary="Home" icon={<FontAwesomeIcon icon={faHome} />} />
<Divider />
{
@@ -141,6 +162,9 @@ export const NavigationMenu = withStyles(styles)(connect()(({ classes, state, di
: null
}
</List>
+ {isOpen && extraLinks && <div className={classes.optLinks}>
+ {extraLinks.map(linkInfo => (<a className={classes.link} href={linkInfo[1]}>{linkInfo[0]}</a>))}
+ </div> || null}
</> || null
}
</Drawer>)
diff --git a/sdnr/wt/odlux/framework/src/index.dev.html b/sdnr/wt/odlux/framework/src/index.dev.html
index 71cb7408d..240da266d 100644
--- a/sdnr/wt/odlux/framework/src/index.dev.html
+++ b/sdnr/wt/odlux/framework/src/index.dev.html
@@ -13,6 +13,12 @@
<div id="app"></div>
<script type="text/javascript" src="./require.js"></script>
<script type="text/javascript" src="./config.js"></script>
+ <script >
+ // window._odluxExtraLinks = [
+ // ["imprint","https://some-url-to-imprint"],
+ // ["privacy declaration", "https://some-url-to-privacy-declaration"]
+ // ]
+ </script>
<script>
// run the application
require(["app" /*,"connectApp","inventoryApp","faultApp","helpApp"*/], function (app,connectApp,inventoryApp,faultApp,helpApp) {
diff --git a/sdnr/wt/odlux/framework/src/views/about.tsx b/sdnr/wt/odlux/framework/src/views/about.tsx
index 59a71512c..db0411793 100644
--- a/sdnr/wt/odlux/framework/src/views/about.tsx
+++ b/sdnr/wt/odlux/framework/src/views/about.tsx
@@ -64,15 +64,19 @@ class AboutComponent extends React.Component<any, AboutState> {
const className = "about-table"
const style: React.CSSProperties = {};
+ const containerStyle = { overflow: "auto", paddingRight: "20px" }
const html = (marked(this.state.content || 'loading', { renderer: markedOptions && markedOptions.renderer || defaultRenderer }));
return (
- <div
- dangerouslySetInnerHTML={{ __html: html }}
- className={className}
- style={style}
- />
+ <div style={containerStyle}>
+ <div
+ dangerouslySetInnerHTML={{ __html: html }}
+ className={className}
+ style={style}
+ />
+ </div>
+
);
}
diff --git a/sdnr/wt/odlux/framework/src/views/frame.tsx b/sdnr/wt/odlux/framework/src/views/frame.tsx
index f2f6f66cc..521897554 100644
--- a/sdnr/wt/odlux/framework/src/views/frame.tsx
+++ b/sdnr/wt/odlux/framework/src/views/frame.tsx
@@ -114,5 +114,4 @@ class FrameComponent extends React.Component<FrameProps>{
}
export const Frame = withStyles(styles)(FrameComponent);
-
export default Frame;