summaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux
diff options
context:
space:
mode:
authorAijana Schumann <aijana.schumann@highstreet-technologies.com>2020-03-13 10:39:11 +0100
committerAijana S <aijana.schumann@highstreet-technologies.com>2020-03-13 10:14:15 +0000
commitce78a6683ab8648ed90e944cd23ed7c01205fce6 (patch)
tree42bac21bac743bdf889639c732aa70b2f747eb29 /sdnr/wt/odlux
parentf3bd99fbe11c443966fff14c6990367b36bdedc4 (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
Diffstat (limited to 'sdnr/wt/odlux')
-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
21 files changed, 319 insertions, 91 deletions
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 967ca2a7e..b7ea291eb 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;