diff --git a/src/Moryx.CommandCenter.Web/package.json b/src/Moryx.CommandCenter.Web/package.json index 26f1f6f8c..23d3fc945 100644 --- a/src/Moryx.CommandCenter.Web/package.json +++ b/src/Moryx.CommandCenter.Web/package.json @@ -12,57 +12,48 @@ "author": "mma", "license": "Apache-2.0", "dependencies": { - "@mdi/js": "^5.0.45", - "@mdi/react": "^1.3.0", - "@types/chart.js": "^2.7.50", - "@types/history": "^4.7.6", - "@types/prop-types": "^15.7.0", - "@types/query-string": "^5.1.0", - "@types/react": "^16.9.25", - "@types/react-dom": "^16.8.3", - "@types/react-notification-system": "^0.2.39", - "@types/react-redux": "^7.0.5", - "@types/reactstrap": "^7.1.3", - "@types/uuid": "^3.4.4", - "bootstrap": "4.3.1", - "bootstrap-toggle": "^2.2.2", - "chart.js": "^2.8.0", - "history": "^4.10.0", - "jquery": "^1.9.1", - "moment": "^2.24.0", - "query-string": "^6.4.0", - "react": "16.8.5", + "@mdi/js": "^7.4.47", + "@mdi/react": "^1.6.1", + "@types/react": "^18.2.55", + "@types/react-dom": "^18.2.19", + "@types/react-redux": "^7.1.33", + "@types/uuid": "^9.0.8", + "bootstrap": "4.6.2", + "bootstrap5-toggle": "^5.0.6", + "history": "^4.10.1", + "moment": "^2.30.1", + "query-string": "^8.2.0", + "react": "18.2.0", "react-bootstrap-toggle": "^2.3.2", - "react-chartjs-2": "^2.7.4", - "react-dom": "16.8.5", - "react-notification-system": "^0.2.17", - "react-redux": "^6.0.1", - "react-router": "^5.3.3", - "react-router-dom": "^5.3.0", + "react-dom": "18.2.0", + "react-redux": "^9.1.0", + "react-router": "^5.3.4", + "react-router-dom": "^5.3.4", "react-router-redux": "^4.0.8", - "reactstrap": "^7.1.0", - "redux": "^4.0.1", - "ts-loader": "^8.1.0", - "uuid": "^9.0.0" + "react-toastify": "^10.0.4", + "reactstrap": "^8.10.1", + "redux": "^5.0.1", + "ts-loader": "^9.5.1", + "uuid": "^9.0.1" }, "devDependencies": { - "@types/react-router": "^5.1.18", + "@types/react-router": "^5.1.20", "@types/react-router-dom": "^5.3.3", - "@types/react-router-redux": "^5.0.21", - "css-loader": "^2.1.1", - "html-webpack-plugin": "^3.2.0", - "node-sass": "^6.0.0", - "sass-loader": "^10.2.1", - "source-map-loader": "^0.2.4", - "style-loader": "^0.23.1", - "tslint": "^5.14.0", + "@types/react-router-redux": "^5.0.27", + "css-loader": "^6.10.0", + "html-webpack-plugin": "^5.6.0", + "node-sass": "^9.0.0", + "sass-loader": "^14.1.0", + "source-map-loader": "^5.0.0", + "style-loader": "^3.3.4", + "tslint": "^6.1.3", "tslint-loader": "^3.5.4", - "tslint-react": "^3.6.0", - "typescript": "^4.8.3", - "url-loader": "^1.1.2", - "webpack": "^4.29.6", - "webpack-cli": "^3.3.0", - "webpack-dev-server": "^3.2.1", - "webpack-merge": "^4.1.2" + "tslint-react": "^5.0.0", + "typescript": "^5.3.3", + "url-loader": "^4.1.1", + "webpack": "^5.90.2", + "webpack-cli": "^5.1.4", + "webpack-dev-server": "^5.0.2", + "webpack-merge": "^5.10.0" } -} +} \ No newline at end of file diff --git a/src/Moryx.CommandCenter.Web/src/common/components/Menu/RoutingMenuItem.tsx b/src/Moryx.CommandCenter.Web/src/common/components/Menu/RoutingMenuItem.tsx index 6cb7b5887..3b86e44d0 100644 --- a/src/Moryx.CommandCenter.Web/src/common/components/Menu/RoutingMenuItem.tsx +++ b/src/Moryx.CommandCenter.Web/src/common/components/Menu/RoutingMenuItem.tsx @@ -6,7 +6,7 @@ import { Location, UnregisterCallback } from "history"; import * as React from "react"; import { Link, RouteComponentProps, withRouter } from "react-router-dom"; -import ListGroupItem from "reactstrap/lib/ListGroupItem"; +import { ListGroupItem } from "reactstrap"; import MenuItemModel from "../../models/MenuItemModel"; interface MenuItemProps { @@ -23,7 +23,7 @@ class RoutingMenuItem extends React.Component & MenuItem private unregisterListenerCallback: UnregisterCallback; constructor(props: RouteComponentProps<{}> & MenuItemProps) { - super (props); + super(props); this.state = { IsOpened: this.isOpened(this.props.location) }; this.unregisterListenerCallback = this.props.history.listen(this.onRouteChanged.bind(this)); diff --git a/src/Moryx.CommandCenter.Web/src/common/components/Panels/WrapPanel.tsx b/src/Moryx.CommandCenter.Web/src/common/components/Panels/WrapPanel.tsx index e1ca6f00c..09f1869c9 100644 --- a/src/Moryx.CommandCenter.Web/src/common/components/Panels/WrapPanel.tsx +++ b/src/Moryx.CommandCenter.Web/src/common/components/Panels/WrapPanel.tsx @@ -10,8 +10,8 @@ export interface WrapPanelProps extends React.HTMLAttributes { children?: React.ReactNode; } -const WrapPanel: React.StatelessComponent = (props, {children}) => { - return
{props.children}
; +const WrapPanel: React.FunctionComponent = (props) => { + return
{props.children}
; }; export default WrapPanel; diff --git a/src/Moryx.CommandCenter.Web/src/common/container/App.tsx b/src/Moryx.CommandCenter.Web/src/common/container/App.tsx index 3efcd1270..63d2542a7 100644 --- a/src/Moryx.CommandCenter.Web/src/common/container/App.tsx +++ b/src/Moryx.CommandCenter.Web/src/common/container/App.tsx @@ -4,13 +4,13 @@ */ import * as React from "react"; -import NotificationSystem = require("react-notification-system"); import { connect } from "react-redux"; import { Redirect, Route, RouteComponentProps, Switch, withRouter } from "react-router-dom"; +import { toast, ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; import { Container } from "reactstrap"; import DatabasesRestClient from "../../databases/api/DatabasesRestClient"; import Databases from "../../databases/container/Databases"; -import LogRestClient from "../../log/api/LogRestClient"; import ModulesRestClient from "../../modules/api/ModulesRestClient"; import Modules from "../../modules/container/Modules"; import { ModuleServerModuleState } from "../../modules/models/ModuleServerModuleState"; @@ -23,7 +23,7 @@ import ApplicationLoadResponse from "../api/responses/ApplicationLoadResponse"; import HostInformationResponse from "../api/responses/HostInformationResponse"; import SystemLoadResponse from "../api/responses/SystemLoadResponse"; import { AppState } from "../redux/AppState"; -import { updateIsConnected, updateNotificationInstance, updateServerTime } from "../redux/CommonActions"; +import { updateIsConnected, updateServerTime } from "../redux/CommonActions"; import { ActionType } from "../redux/Types"; import "../scss/commandcenter.scss"; @@ -31,7 +31,6 @@ interface AppPropModel { ModulesRestClient: ModulesRestClient; CommonRestClient: CommonRestClient; DatabasesRestClient: DatabasesRestClient; - LogRestClient: LogRestClient; IsConnected: boolean; ShowWaitDialog: boolean; Modules: ServerModuleModel[]; @@ -47,7 +46,6 @@ interface AppDispatchPropModel { onUpdateModuleHealthState?(moduleName: string, healthState: ModuleServerModuleState): void; onUpdateModuleNotifications?(moduleName: string, notifications: NotificationModel[]): void; onUpdateIsConnected?(isConnected: boolean): void; - onUpdateNotificationSystemInstance?(notificationSystem: NotificationSystem): void; } const mapStateToProps = (state: AppState): AppPropModel => { @@ -55,7 +53,6 @@ const mapStateToProps = (state: AppState): AppPropModel => { ModulesRestClient: state.Modules.RestClient, CommonRestClient: state.Common.RestClient, DatabasesRestClient: state.Databases.RestClient, - LogRestClient: state.Log.RestClient, IsConnected: state.Common.IsConnected, ShowWaitDialog: state.Common.ShowWaitDialog, Modules: state.Modules.Modules, @@ -64,22 +61,19 @@ const mapStateToProps = (state: AppState): AppPropModel => { const mapDispatchToProps = (dispatch: React.Dispatch>): AppDispatchPropModel => { return { - onUpdateServerTime: (serverTime: string) => dispatch(updateServerTime(serverTime)), - onUpdateModules: (modules: ServerModuleModel[]) => dispatch(updateModules(modules)), - onUpdateModuleHealthState: (moduleName: string, healthState: ModuleServerModuleState) => - dispatch(updateHealthState(moduleName, healthState)), - onUpdateModuleNotifications: (moduleName: string, notifications: NotificationModel[]) => - dispatch(updateNotifications(moduleName, notifications)), - onUpdateIsConnected: (isConnected: boolean) => dispatch(updateIsConnected(isConnected)), - onUpdateNotificationSystemInstance: (notificationSystem: NotificationSystem) => - dispatch(updateNotificationInstance(notificationSystem)), + onUpdateServerTime: (serverTime: string) => dispatch(updateServerTime(serverTime)), + onUpdateModules: (modules: ServerModuleModel[]) => dispatch(updateModules(modules)), + onUpdateModuleHealthState: (moduleName: string, healthState: ModuleServerModuleState) => + dispatch(updateHealthState(moduleName, healthState)), + onUpdateModuleNotifications: (moduleName: string, notifications: NotificationModel[]) => + dispatch(updateNotifications(moduleName, notifications)), + onUpdateIsConnected: (isConnected: boolean) => dispatch(updateIsConnected(isConnected)) }; }; class App extends React.Component & AppDispatchPropModel> { private updateClockTimer: NodeJS.Timeout; private updateLoadAndModulesTimer: NodeJS.Timeout; - private notificationSystem: NotificationSystem = null; constructor(props: AppPropModel & RouteComponentProps<{}> & AppDispatchPropModel) { super(props); @@ -98,23 +92,16 @@ class App extends React.Component & AppDi } public render(): React.ReactNode { - const ref = (instance: NotificationSystem) => { - if (this.notificationSystem == null) { - this.notificationSystem = instance; - this.props?.onUpdateNotificationSystemInstance(instance); - } - }; - return (
- + - + } />
@@ -135,5 +122,5 @@ class App extends React.Component & AppDi } export default withRouter, React.ComponentType>( -connect(mapStateToProps, mapDispatchToProps)(App) + connect(mapStateToProps, mapDispatchToProps)(App) ); diff --git a/src/Moryx.CommandCenter.Web/src/common/redux/AppState.ts b/src/Moryx.CommandCenter.Web/src/common/redux/AppState.ts index bc7ea84f2..46fb9b675 100644 --- a/src/Moryx.CommandCenter.Web/src/common/redux/AppState.ts +++ b/src/Moryx.CommandCenter.Web/src/common/redux/AppState.ts @@ -3,35 +3,27 @@ * Licensed under the Apache License, Version 2.0 */ -import { DashboardState, getDashboardReducer, initialDashboardState } from "../../dashboard/redux/DashboardState"; import { DatabaseState, getDatabaseReducer, initialDatabaseState } from "../../databases/redux/DatabaseState"; -import { getLogReducer, initialLogState, LogState } from "../../log/redux/LogState"; import { getModulesReducer, initialModulesState, ModulesState } from "../../modules/redux/ModulesState"; import { CommonState, getCommonReducer, initialCommonState } from "./CommonState"; import { ActionType } from "./Types"; export interface AppState { Common: CommonState; - Dashboard: DashboardState; Modules: ModulesState; Databases: DatabaseState; - Log: LogState; } export const initialAppState: AppState = { Common: initialCommonState, - Dashboard: initialDashboardState, Modules: initialModulesState, Databases: initialDatabaseState, - Log: initialLogState, }; export function getAppReducer(state: AppState = initialAppState, action: ActionType<{}>): AppState { return { Common: getCommonReducer(state.Common, action), - Dashboard: getDashboardReducer(state.Dashboard, action), Modules: getModulesReducer(state.Modules, action), Databases: getDatabaseReducer(state.Databases, action), - Log: getLogReducer(state.Log, action), }; } diff --git a/src/Moryx.CommandCenter.Web/src/common/redux/CommonActions.ts b/src/Moryx.CommandCenter.Web/src/common/redux/CommonActions.ts index 5bb2ca7f4..8283c57d0 100644 --- a/src/Moryx.CommandCenter.Web/src/common/redux/CommonActions.ts +++ b/src/Moryx.CommandCenter.Web/src/common/redux/CommonActions.ts @@ -3,7 +3,6 @@ * Licensed under the Apache License, Version 2.0 */ -import NotificationSystem = require("react-notification-system"); import { ActionType } from "./Types"; export const UPDATE_SERVER_TIME = "UPDATE_SERVER_TIME"; @@ -19,10 +18,6 @@ export function updateIsConnected(isConnected: boolean): ActionType { return { type: UPDATE_IS_CONNECTED, payload: isConnected }; } -export function updateNotificationInstance(notificationSystem: NotificationSystem): ActionType { - return { type: UPDATE_NOTIFICATION_INSTANCE, payload: notificationSystem }; -} - export function updateShowWaitDialog(showWaitDialog: boolean): ActionType { return { type: UPDATE_SHOW_WAIT_DIALOG, payload: showWaitDialog }; } diff --git a/src/Moryx.CommandCenter.Web/src/common/redux/CommonState.ts b/src/Moryx.CommandCenter.Web/src/common/redux/CommonState.ts index 944e2a491..25a6d9645 100644 --- a/src/Moryx.CommandCenter.Web/src/common/redux/CommonState.ts +++ b/src/Moryx.CommandCenter.Web/src/common/redux/CommonState.ts @@ -4,7 +4,6 @@ */ require("../../types/constants"); -import NotificationSystem = require("react-notification-system"); import CommonRestClient from "../api/CommonRestClient"; import { UPDATE_IS_CONNECTED, UPDATE_NOTIFICATION_INSTANCE, UPDATE_SERVER_TIME, UPDATE_SHOW_WAIT_DIALOG } from "./CommonActions"; import { ActionType } from "./Types"; @@ -14,31 +13,26 @@ export interface CommonState { ServerTime: string; RestClient: CommonRestClient; ShowWaitDialog: boolean; - NotificationSystem: NotificationSystem; } export const initialCommonState: CommonState = { IsConnected: true, - NotificationSystem: null, RestClient: new CommonRestClient(BASE_URL), ServerTime: "", ShowWaitDialog: false, }; export function getCommonReducer(state: CommonState = initialCommonState, action: ActionType<{}>): CommonState { - switch (action.type) { - case UPDATE_SERVER_TIME: { - return { ...state, ServerTime: action.payload as string }; + switch (action.type) { + case UPDATE_SERVER_TIME: { + return { ...state, ServerTime: action.payload as string }; + } + case UPDATE_IS_CONNECTED: { + return { ...state, IsConnected: action.payload as boolean }; + } + case UPDATE_SHOW_WAIT_DIALOG: { + return { ...state, ShowWaitDialog: action.payload as boolean }; + } } - case UPDATE_IS_CONNECTED: { - return { ...state, IsConnected: action.payload as boolean }; - } - case UPDATE_NOTIFICATION_INSTANCE: { - return { ...state, NotificationSystem: action.payload as NotificationSystem }; - } - case UPDATE_SHOW_WAIT_DIALOG: { - return { ...state, ShowWaitDialog: action.payload as boolean }; - } - } - return state; + return state; } diff --git a/src/Moryx.CommandCenter.Web/src/dashboard/components/CPUMemoryChart.tsx b/src/Moryx.CommandCenter.Web/src/dashboard/components/CPUMemoryChart.tsx deleted file mode 100644 index 188faba47..000000000 --- a/src/Moryx.CommandCenter.Web/src/dashboard/components/CPUMemoryChart.tsx +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ - -import * as chartjs from "chart.js"; -import * as React from "react"; -import { ChartData, Line } from "react-chartjs-2"; -import SystemLoadSample from "../../common/models/SystemLoadSample"; - -interface CPUMemoryPropsModel { - Samples: SystemLoadSample[]; -} - -interface CPUMemoryStateModel { - chartData: any; -} - -export class CPUMemoryChart extends React.Component { - constructor(props: CPUMemoryPropsModel) { - super(props); - this.state = { - chartData: CPUMemoryChart.createChartData(), - }; - } - - public componentDidMount(): void { - this.updateChartData(this.props); - } - - public componentWillReceiveProps(nextProps: CPUMemoryPropsModel): void { - this.updateChartData(nextProps); - } - - public updateChartData(nextProps: CPUMemoryPropsModel): void { - const chartData = CPUMemoryChart.createChartData(); - nextProps.Samples.forEach((sample) => { - chartData.labels.push(sample.Date); - chartData.datasets[0].data.push(sample.CPULoad); - chartData.datasets[1].data.push(sample.SystemMemoryLoad); - }); - - this.setState({chartData}); - } - - private static createChartData(): any { - const chartData: ChartData = { - labels: [], - datasets: - [ - { - label: "CPU load (%)", - fill: false, - lineTension: 0.1, - backgroundColor: "rgba(218, 165, 32, 0.5)", - data: [], - }, - { - label: "Used memory (%)", - fill: false, - lineTension: 0.1, - backgroundColor: "rgba(0, 0, 255, 0.5)", - data: [], - }, - ], - }; - return chartData; - } - - public render(): React.ReactNode { - return ( - - ); - } -} diff --git a/src/Moryx.CommandCenter.Web/src/dashboard/components/Module.tsx b/src/Moryx.CommandCenter.Web/src/dashboard/components/Module.tsx deleted file mode 100644 index 142f348ef..000000000 --- a/src/Moryx.CommandCenter.Web/src/dashboard/components/Module.tsx +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ - -import { mdiHexagon } from "@mdi/js"; -import Icon from "@mdi/react"; -import * as React from "react"; -import { Link } from "react-router-dom"; -import { Card, CardBody, CardHeader, Col, Container, Row } from "reactstrap"; -import ServerModuleModel from "../../modules/models/ServerModuleModel"; -import { HealthStateToCssClassConverter } from "../converter/HealthStateToCssClassConverter"; -import { HealthStateBadge } from "./HealthStateBadge"; - -interface ModulePropsModel { - ServerModule: ServerModuleModel; -} - -export class Module extends React.Component { - - constructor(props: ModulePropsModel) { - super(props); - this.state = {}; - } - - public render(): React.ReactNode { - const stateCssClass = HealthStateToCssClassConverter.Convert(this.props.ServerModule.healthState); - - return ( -
- - - - - {this.props.ServerModule.name} - - - - - - State: - - - - Assembly: - {this.props.ServerModule.assembly.name} - - - Version: - {this.props.ServerModule.assembly.version} - - - Info: - {this.props.ServerModule.assembly.informationalVersion} - - - - -
- ); - } -} diff --git a/src/Moryx.CommandCenter.Web/src/dashboard/container/Dashboard.tsx b/src/Moryx.CommandCenter.Web/src/dashboard/container/Dashboard.tsx deleted file mode 100644 index dfe3a9c9e..000000000 --- a/src/Moryx.CommandCenter.Web/src/dashboard/container/Dashboard.tsx +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ - -import { mdiViewDashboard } from "@mdi/js"; -import Icon from "@mdi/react"; -import * as React from "react"; -import { connect } from "react-redux"; -import { Card, CardBody, CardHeader, Col, Container, Progress, Row } from "reactstrap"; -import CommonRestClient from "../../common/api/CommonRestClient"; -import ApplicationInformationResponse from "../../common/api/responses/ApplicationInformationResponse"; -import ApplicationLoadResponse from "../../common/api/responses/ApplicationLoadResponse"; -import HostInformationResponse from "../../common/api/responses/HostInformationResponse"; -import WrapPanel from "../../common/components/Panels/WrapPanel"; -import kbToString from "../../common/converter/ByteConverter"; -import SystemLoadSample from "../../common/models/SystemLoadSample"; -import { AppState } from "../../common/redux/AppState"; -import { ActionType } from "../../common/redux/Types"; -import ServerModuleModel from "../../modules/models/ServerModuleModel"; -import { updateModules } from "../../modules/redux/ModulesActions"; -import { CPUMemoryChart } from "../components/CPUMemoryChart"; -import { Module } from "../components/Module"; - -interface DashboardPropModel { - ApplicationInfo: ApplicationInformationResponse; - HostInfo: HostInformationResponse; - ApplicationLoad: ApplicationLoadResponse; - SystemLoad: SystemLoadSample[]; - Modules: ServerModuleModel[]; - RestClient: CommonRestClient; -} - -const mapStateToProps = (state: AppState): DashboardPropModel => { - return { - ApplicationInfo: state.Dashboard.ApplicationInfo, - HostInfo: state.Dashboard.HostInfo, - ApplicationLoad: state.Dashboard.ApplicationLoad, - SystemLoad: state.Dashboard.SystemLoad, - Modules: state.Modules.Modules, - RestClient: state.Common.RestClient, - }; -}; - -class Dashboard extends React.Component { - private restCallDate: number; - - constructor(props: DashboardPropModel) { - super(props); - - this.restCallDate = Date.now(); - } - - public calculateMemoryUsagePercentage(): number { - return Math.round((this.props.ApplicationLoad.workingSet / this.props.ApplicationLoad.systemMemory) * 100.0); - } - - public preRenderModules(): React.ReactNode { - return this.props.Modules.map((module, idx) => ); - } - - public render(): React.ReactNode { - return ( - - - - Dashboard - - - - - -

Application

- - - Name: - {this.props.ApplicationInfo.assemblyProduct} - - - Description: - {this.props.ApplicationInfo.assemblyDescription} - - - Version: - {this.props.ApplicationInfo.assemblyVersion} ({this.props.ApplicationInfo.assemblyInformationalVersion}) - - - CPU usage: - {this.props.ApplicationLoad.cpuLoad}% - - - - - - Memory usage: - {kbToString(this.props.ApplicationLoad.workingSet)} ({kbToString(this.props.ApplicationLoad.systemMemory)}) - - - - - - - -

Server

- - - Hostname: - {this.props.HostInfo.machineName} - - - OS: - {this.props.HostInfo.osInformation} - - - Up since: - {new Date(this.restCallDate - this.props.HostInfo.upTime).toLocaleString()} - - - - -

CPU & Memory

- - -
- - -

Modules

- - {this.preRenderModules()} - - -
-
-
-
- ); - } -} - -export default connect(mapStateToProps)(Dashboard); diff --git a/src/Moryx.CommandCenter.Web/src/dashboard/redux/DashboardActions.ts b/src/Moryx.CommandCenter.Web/src/dashboard/redux/DashboardActions.ts deleted file mode 100644 index 9ea4aeb2f..000000000 --- a/src/Moryx.CommandCenter.Web/src/dashboard/redux/DashboardActions.ts +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ - -import ApplicationInformationResponse from "../../common/api/responses/ApplicationInformationResponse"; -import ApplicationLoadResponse from "../../common/api/responses/ApplicationLoadResponse"; -import HostInformationResponse from "../../common/api/responses/HostInformationResponse"; -import SystemLoadResponse from "../../common/api/responses/SystemLoadResponse"; -import { ActionType } from "../../common/redux/Types"; - -export const UPDATE_APPLICATION_INFO = "UPDATE_APPLICATION_INFO"; -export const UPDATE_HOST_INFO = "UPDATE_HOST_INFO"; -export const UPDATE_APPLICATION_LOAD = "UPDATE_APPLICATION_LOAD"; -export const UPDATE_SYSTEM_LOAD = "UPDATE_SYSTEM_LOAD"; - -export function updateApplicationInfo(applicationInfo: ApplicationInformationResponse): ActionType { - return { type: UPDATE_APPLICATION_INFO, payload: applicationInfo }; -} - -export function updateHostInfo(hostInfo: HostInformationResponse): ActionType { - return { type: UPDATE_HOST_INFO, payload: hostInfo }; -} - -export function updateApplicationLoad(applicationLoad: ApplicationLoadResponse): ActionType { - return { type: UPDATE_APPLICATION_LOAD, payload: applicationLoad }; -} - -export function updateSystemLoad(systemLoad: SystemLoadResponse): ActionType { - return { type: UPDATE_SYSTEM_LOAD, payload: systemLoad }; -} diff --git a/src/Moryx.CommandCenter.Web/src/dashboard/redux/DashboardState.ts b/src/Moryx.CommandCenter.Web/src/dashboard/redux/DashboardState.ts deleted file mode 100644 index 49148a711..000000000 --- a/src/Moryx.CommandCenter.Web/src/dashboard/redux/DashboardState.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ - -import ApplicationInformationResponse from "../../common/api/responses/ApplicationInformationResponse"; -import ApplicationLoadResponse from "../../common/api/responses/ApplicationLoadResponse"; -import HostInformationResponse from "../../common/api/responses/HostInformationResponse"; -import SystemLoadResponse from "../../common/api/responses/SystemLoadResponse"; -import SystemLoadSample from "../../common/models/SystemLoadSample"; -import { ActionType } from "../../common/redux/Types"; -import { UPDATE_APPLICATION_INFO, UPDATE_APPLICATION_LOAD, UPDATE_HOST_INFO, UPDATE_SYSTEM_LOAD } from "./DashboardActions"; - -export interface DashboardState { - ApplicationInfo: ApplicationInformationResponse; - HostInfo: HostInformationResponse; - ApplicationLoad: ApplicationLoadResponse; - SystemLoad: SystemLoadSample[]; -} - -export const initialDashboardState: DashboardState = { - ApplicationInfo: { assemblyProduct: "", assemblyVersion: "", assemblyInformationalVersion: "", assemblyDescription: "" }, - HostInfo: { machineName: "", osInformation: "", upTime: 0 }, - ApplicationLoad: { cpuLoad: 0, systemMemory: 0, workingSet: 0 }, - SystemLoad: [], -}; - -export function getDashboardReducer(state: DashboardState = initialDashboardState, action: ActionType<{}>): DashboardState { - switch (action.type) { - case UPDATE_APPLICATION_INFO: { - return { ...state, ApplicationInfo: action.payload as ApplicationInformationResponse }; - } - case UPDATE_HOST_INFO: { - return { ...state, HostInfo: action.payload as HostInformationResponse }; - } - case UPDATE_APPLICATION_LOAD: { - return { ...state, ApplicationLoad: action.payload as ApplicationLoadResponse }; - } - case UPDATE_SYSTEM_LOAD: { - const systemLoadResponse = action.payload as SystemLoadResponse; - const samples = state.SystemLoad.slice(); - if (samples.length === 5) { - samples.shift(); - } - - samples.push({ Date: new Date(Date.now()).toLocaleString(), CPULoad: systemLoadResponse.cpuLoad, SystemMemoryLoad: systemLoadResponse.systemMemoryLoad }); - - return { ...state, SystemLoad: samples }; - } - } - return state; -} diff --git a/src/Moryx.CommandCenter.Web/src/databases/container/DatabaseModel.tsx b/src/Moryx.CommandCenter.Web/src/databases/container/DatabaseModel.tsx index 5d8f33e17..6794a56c5 100644 --- a/src/Moryx.CommandCenter.Web/src/databases/container/DatabaseModel.tsx +++ b/src/Moryx.CommandCenter.Web/src/databases/container/DatabaseModel.tsx @@ -3,14 +3,14 @@ * Licensed under the Apache License, Version 2.0 */ -import { mdiBriefcase, mdiCheck, mdiDatabase, mdiExclamationThick, mdiLoading, mdiPowerPlug, mdiTable} from "@mdi/js"; +import { mdiBriefcase, mdiCheck, mdiDatabase, mdiExclamationThick, mdiLoading, mdiPowerPlug, mdiTable } from "@mdi/js"; import Icon from "@mdi/react"; import * as moment from "moment"; import { any, element, string } from "prop-types"; import * as React from "react"; -import NotificationSystem = require("react-notification-system"); import { connect, Provider } from "react-redux"; import { RouteComponentProps, withRouter } from "react-router-dom"; +import { toast, ToastContainer } from "react-toastify"; import { Button, ButtonGroup, Card, CardBody, CardHeader, Col, Container, Form, Input, Nav, NavItem, NavLink, Row, TabContent, TabPane, UncontrolledTooltip } from "reactstrap"; import kbToString from "../../common/converter/ByteConverter"; import { updateShowWaitDialog } from "../../common/redux/CommonActions"; @@ -26,7 +26,6 @@ import { updateDatabaseConfig } from "../redux/DatabaseActions"; interface DatabaseModelPropsModel { RestClient: DatabasesRestClient; DataModel: DataModel; - NotificationSystem: NotificationSystem; } interface DatabaseModelStateModel { @@ -57,10 +56,10 @@ class DatabaseModel extends React.Component): void { - this.setState({selectedMigration: (e.target as HTMLSelectElement).value}); + this.setState({ selectedMigration: (e.target as HTMLSelectElement).value }); } public onSelectSetup(e: React.FormEvent): void { - this.setState({selectedSetup: (e.target as HTMLSelectElement).selectedIndex}); + this.setState({ selectedSetup: (e.target as HTMLSelectElement).selectedIndex }); } public getValidationState(entryName: string) { const result = this.props.DataModel.possibleConfigurators.find((x) => x.configuratorTypename === this.state.config.configuratorTypename) - ?.properties.find((x) => x.name === entryName).required ? - (this.state.config.entries[entryName] ? {valid : true, invalid : false} : {invalid : true , valid : false}) : {valid : true, invalid : false}; + ?.properties.find((x) => x.name === entryName).required ? + (this.state.config.entries[entryName] ? { valid: true, invalid: false } : { invalid: true, valid: false }) : { valid: true, invalid: false }; return result; } public onConfiguratorTypeChanged(e: React.FormEvent): void { - this.setState({config: {...this.state.config, configuratorTypename: (e.target as HTMLSelectElement).value , - entries: this.getConfigWithDefaultValue((e.target as HTMLSelectElement).value)}}); + this.setState({ + config: { + ...this.state.config, configuratorTypename: (e.target as HTMLSelectElement).value, + entries: this.getConfigWithDefaultValue((e.target as HTMLSelectElement).value) + } + }); } public onInputChanged(e: React.FormEvent, entryName: string): void { this.setState({ - config : {...this.state.config, entries : {...this.state.config.entries, [entryName]: (e.target as HTMLSelectElement).value}} + config: { ...this.state.config, entries: { ...this.state.config.entries, [entryName]: (e.target as HTMLSelectElement).value } } }); } public onSelectBackup(e: React.FormEvent): void { - this.setState({selectedBackup: (e.target as HTMLSelectElement).value}); + this.setState({ selectedBackup: (e.target as HTMLSelectElement).value }); } public createEntriesInput() { return Object.keys(this.state.config.entries)?.map((element) => { return ( - this.onTestConnection()} onChange={(e: React.FormEvent) => this.onInputChanged(e, element)}/> - ); - }); + this.onTestConnection()} onChange={(e: React.FormEvent) => this.onInputChanged(e, element)} /> + ); + }); } public getConfigEntries() { @@ -134,9 +137,10 @@ class DatabaseModel extends React.Component { this.props.onShowWaitDialog(false); - this.setState({config: response.config}); + this.setState({ config: response.config }); this.props.onUpdateDatabaseConfig(response); - this.props.NotificationSystem.addNotification({ title: "Configuration saved", message: "", level: "success", autoDismiss: 5 }); + toast.success("Configuration saved", { autoClose: 5000 }); this.onTestConnection(); }).catch((d) => this.props.onShowWaitDialog(false)); } @@ -157,10 +161,12 @@ class DatabaseModel extends React.Component { - this.setState({ testConnectionPending: false, - testConnectionResult: response.result !== undefined ? response.result : TestConnectionResult.ConnectionError }); - }); + .then((response) => { + this.setState({ + testConnectionPending: false, + testConnectionResult: response.result !== undefined ? response.result : TestConnectionResult.ConnectionError + }); + }); } public onCreateDatabase(): void { @@ -171,10 +177,10 @@ class DatabaseModel extends React.Component this.props.onUpdateDatabaseConfig(databaseConfig)); - this.props.NotificationSystem.addNotification({ title: "Success", message: "Database created successfully", level: "success", autoDismiss: 5 }); - } else { - this.props.NotificationSystem.addNotification({ title: "Error", message: "Database not created: " + data.errorMessage, level: "error", autoDismiss: 5 }); - } + toast.success("Database created successfully", { autoClose: 5000 }); + } else { + toast.error("Database not created: " + data.errorMessage, { autoClose: 5000 }); + } this.onTestConnection(); }).catch((d) => this.props.onShowWaitDialog(false)); } @@ -191,9 +197,9 @@ class DatabaseModel extends React.Component this.props.onUpdateDatabaseConfig(databaseConfig)); - this.props.NotificationSystem.addNotification({ title: "Success", message: "Database deleted successfully", level: "success", autoDismiss: 5 }); + toast.success("Database deleted successfully", { autoClose: 5000 }); } else { - this.props.NotificationSystem.addNotification({ title: "Error", message: "Database not deleted: " + data.errorMessage, level: "error", autoDismiss: 5 }); + toast.error("Database not deleted: " + data.errorMessage, { autoClose: 5000 }); } this.onTestConnection(); }).catch((d) => this.props.onShowWaitDialog(false)); @@ -205,9 +211,9 @@ class DatabaseModel extends React.Component { this.props.onShowWaitDialog(false); if (data.success) { - this.props.NotificationSystem.addNotification({ title: "Success", message: "Database dump started successfully. Please refer to the log to get information about the progress.", level: "success", autoDismiss: 5 }); + toast.success("Database dump started successfully. Please refer to the log to get information about the progress.", { autoClose: 5000 }); } else { - this.props.NotificationSystem.addNotification({ title: "Error", message: "Dump start failed: " + data.errorMessage, level: "error", autoDismiss: 5 }); + toast.error("Dump start failed: " + data.errorMessage, { autoClose: 5000 }); } }).catch((d) => this.props.onShowWaitDialog(false)); } @@ -218,9 +224,9 @@ class DatabaseModel extends React.Component { this.props.onShowWaitDialog(false); if (data.success) { - this.props.NotificationSystem.addNotification({ title: "Success", message: "Database restore started successfully. Please refer to the log to get information about the progress.", level: "success", autoDismiss: 5 }); + toast.success("Database restore started successfully. Please refer to the log to get information about the progress.", { autoClose: 5000 }); } else { - this.props.NotificationSystem.addNotification({ title: "Error", message: "Restore start failed: " + data.errorMessage, level: "error", autoDismiss: 5 }); + toast.error("Restore start failed: " + data.errorMessage, { autoClose: 5000 }); } }).catch((d) => this.props.onShowWaitDialog(false)); } @@ -233,9 +239,9 @@ class DatabaseModel extends React.Component this.props.onUpdateDatabaseConfig(databaseConfig)); - this.props.NotificationSystem.addNotification({ title: "Success", message: "Migration applied", level: "success", autoDismiss: 5 }); + toast.success("Migration applied", { autoClose: 5000 }); } else { - this.props.NotificationSystem.addNotification({ title: "Error", message: "Migration not applied", level: "error", autoDismiss: 5 }); + toast.error("Migration not applied", { autoClose: 5000 }); } }).catch((d) => this.props.onShowWaitDialog(false)); } @@ -248,9 +254,9 @@ class DatabaseModel extends React.Component this.props.onUpdateDatabaseConfig(databaseConfig)); - this.props.NotificationSystem.addNotification({ title: "Success", message: "Database rollback completed successfully", level: "success", autoDismiss: 5 }); + toast.success("Database rollback completed successfully", { autoClose: 5000 }); } else { - this.props.NotificationSystem.addNotification({ title: "Error", message: "Database rollback failed: " + data.errorMessage, level: "error", autoDismiss: 5 }); + toast.error("Database rollback failed: " + data.errorMessage, { autoClose: 5000 }); } }).catch((d) => this.props.onShowWaitDialog(false)); } @@ -264,9 +270,9 @@ class DatabaseModel extends React.Component this.props.onShowWaitDialog(false)); } @@ -276,29 +282,29 @@ class DatabaseModel extends React.Component); case TestConnectionResult.ConfigurationError: - return (
- - - - Please check if model configuration exists on server. - -
); + return (
+ + + + Please check if model configuration exists on server. + +
); case TestConnectionResult.ConnectionError: - return (
- - - - Please check Database name and connection string. - -
); + return (
+ + + + Please check Database name and connection string. + +
); case TestConnectionResult.ConnectionOkDbDoesNotExist: - return (
- - - - The connection to the database could be established but the database could not be found. Please check the name of the database or create it before. - -
); + return (
+ + + + The connection to the database could be established but the database could not be found. Please check the name of the database or create it before. + +
); default: return (
); } @@ -317,9 +323,9 @@ class DatabaseModel extends React.Component

Connection Settings - { this.state.testConnectionPending ? ( - - ) : this.preRenderConnectionCheckIcon() } + {this.state.testConnectionPending ? ( + + ) : this.preRenderConnectionCheckIcon()}

@@ -328,10 +334,10 @@ class DatabaseModel extends React.Component - ) => this.onConfiguratorTypeChanged(e)} - value={this.state.config.configuratorTypename} onBlur={() => this.onTestConnection()}> - {this.props.DataModel.possibleConfigurators.map((config, idx) => ())} - + ) => this.onConfiguratorTypeChanged(e)} + value={this.state.config.configuratorTypename} onBlur={() => this.onTestConnection()}> + {this.props.DataModel.possibleConfigurators.map((config, idx) => ())} + {this.state.config.configuratorTypename && this.createEntriesInput()} @@ -347,7 +353,7 @@ class DatabaseModel extends React.Component ) => this.onSelectBackup(e)}> + onChange={(e: React.FormEvent) => this.onSelectBackup(e)}> { this.props.DataModel.backups.map((backup, idx) => { return (); @@ -361,13 +367,13 @@ class DatabaseModel extends React.Component @@ -379,27 +385,27 @@ class DatabaseModel extends React.Component - - -

Database

- -
- - - - - - - - + + +

Database

+ +
+ + + + + + + +
@@ -415,41 +421,41 @@ class DatabaseModel extends React.Component - { this.props.DataModel.availableMigrations.length !== 0 ? + {this.props.DataModel.availableMigrations.length !== 0 ? ( - - - - ) => this.onSelectMigration(e)}> - { - this.props.DataModel.availableMigrations.map((migration, idx) => { - const installed = this.props.DataModel.appliedMigrations.find((installedMigration: DbMigrationsModel) => installedMigration.name === migration.name); - const option = migration.name + " (" + (installed ? "Installed" : "Not installed") + ")"; - - return (); - }) - } - - - - - - - - - - - - + Rollback all migrations + + + + + ) : ( @@ -459,31 +465,31 @@ class DatabaseModel extends React.Component - { this.props.DataModel.setups.length !== 0 ? + {this.props.DataModel.setups.length !== 0 ? ( - - - - ) => this.onSelectSetup(e)}> - { - this.props.DataModel.setups.map((setup, idx) => { - return (); - }) - } - - - - - - - - - + Execute setup + + + + ) : ( diff --git a/src/Moryx.CommandCenter.Web/src/databases/container/Databases.tsx b/src/Moryx.CommandCenter.Web/src/databases/container/Databases.tsx index 381276241..a91dc673d 100644 --- a/src/Moryx.CommandCenter.Web/src/databases/container/Databases.tsx +++ b/src/Moryx.CommandCenter.Web/src/databases/container/Databases.tsx @@ -3,17 +3,12 @@ * Licensed under the Apache License, Version 2.0 */ -import { mdiBriefcase, mdiComment, mdiDatabase, mdiHexagonMultiple} from "@mdi/js"; +import { mdiBriefcase, mdiComment, mdiDatabase, mdiHexagonMultiple } from "@mdi/js"; import Icon from "@mdi/react"; import * as React from "react"; -import NotificationSystem = require("react-notification-system"); import { connect } from "react-redux"; import { Link, Route, RouteComponentProps, Switch } from "react-router-dom"; -import { Card, CardBody, CardHeader, Col, Row } from "reactstrap"; -import ListGroup from "reactstrap/lib/ListGroup"; -import Nav from "reactstrap/lib/Nav"; -import Navbar from "reactstrap/lib/Navbar"; -import NavItem from "reactstrap/lib/NavItem"; +import { Card, CardBody, CardHeader, Col, ListGroup, Nav, Navbar, NavItem, Row } from "reactstrap"; import RoutingMenu from "../../common/components/Menu/RoutingMenu"; import MenuItemModel from "../../common/models/MenuItemModel"; import MenuModel from "../../common/models/MenuModel"; @@ -27,7 +22,6 @@ import DatabaseModel from "./DatabaseModel"; interface DatabasesPropsModel { RestClient?: DatabasesRestClient; DatabaseConfigs?: DataModel[]; - NotificationSystem?: NotificationSystem; } interface DatabasesDispatchPropModel { @@ -37,8 +31,7 @@ interface DatabasesDispatchPropModel { const mapStateToProps = (state: AppState): DatabasesPropsModel => { return { RestClient: state.Databases.RestClient, - DatabaseConfigs: state.Databases.DatabaseConfigs, - NotificationSystem: state.Common.NotificationSystem, + DatabaseConfigs: state.Databases.DatabaseConfigs }; }; @@ -80,7 +73,7 @@ class Database extends React.Component{namespace}

), + Content: (

{namespace}

), SubMenuItems: [], }; } @@ -90,7 +83,10 @@ class Database extends React.Component { - routes.push( }/>); + routes.push( + + + ); ++idx; }); @@ -103,25 +99,25 @@ class Database extends React.Component - - - + + + - { this.state.IsLoading ? ( + {this.state.IsLoading ? ( Loading... ) : ( @@ -131,7 +127,7 @@ class Database extends React.Component - + @@ -141,7 +137,7 @@ class Database extends React.ComponentConfigure all available database models. Please select a database model to proceed... - } /> + {this.preRenderRoutesList()} diff --git a/src/Moryx.CommandCenter.Web/src/log/api/LogRestClient.ts b/src/Moryx.CommandCenter.Web/src/log/api/LogRestClient.ts deleted file mode 100644 index ba0453105..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/api/LogRestClient.ts +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ -import InvocationResponse from "../../common/api/responses/InvocationResponse"; -import RestClientBase from "../../common/api/RestClientBase"; -import LoggerModel from "../models/LoggerModel"; -import { LogLevel } from "../models/LogLevel"; -import LogMessageModel from "../models/LogMessageModel"; -import AddRemoteAppenderRequest from "./requests/AddRemoteAppenderRequest"; -import SetLogLevelRequest from "./requests/SetLogLevelRequest"; -import AddAppenderResponse from "./responses/AddAppenderResponse"; - -const ROOT_PATH = "/loggers"; -const APPENDER_PATH = ROOT_PATH + "/appenders"; - -export default class LogRestClient extends RestClientBase { - public loggers(): Promise { - return this.get(ROOT_PATH, []); - } - - public addRemoteAppender(name: string, minLevel: LogLevel): Promise { - const request = new AddRemoteAppenderRequest(); - request.MinLevel = minLevel; - request.Name = name; - return this.post(APPENDER_PATH, request, new AddAppenderResponse()); - } - - public removeRemoteAppender(appenderId: number): Promise { - return this.deleteNoBody(LogRestClient.pathToAppender(appenderId), new InvocationResponse()); - } - - public messages(appenderId: number): Promise { - return this.get(LogRestClient.pathToAppender(appenderId), []); - } - - public logLevel(loggerName: string, level: LogLevel): Promise { - const request = new SetLogLevelRequest(); - request.Level = level; - return this.put(ROOT_PATH + `/${loggerName}/loglevel`, request, new InvocationResponse()); - } - - public static pathToAppender(appenderId: number): string { - return APPENDER_PATH + `/${appenderId.toString()}`; - } -} diff --git a/src/Moryx.CommandCenter.Web/src/log/api/requests/AddRemoteAppenderRequest.ts b/src/Moryx.CommandCenter.Web/src/log/api/requests/AddRemoteAppenderRequest.ts deleted file mode 100644 index ec37ca63a..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/api/requests/AddRemoteAppenderRequest.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ -import { LogLevel } from "../../models/LogLevel"; - -export default class AddRemoteAppenderRequest { - public Name: string; - public MinLevel: LogLevel; -} diff --git a/src/Moryx.CommandCenter.Web/src/log/api/requests/SetLogLevelRequest.ts b/src/Moryx.CommandCenter.Web/src/log/api/requests/SetLogLevelRequest.ts deleted file mode 100644 index 88cd3fdf4..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/api/requests/SetLogLevelRequest.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ -import { LogLevel } from "../../models/LogLevel"; - -export default class SetLogLevelRequest { - public Level: LogLevel; -} diff --git a/src/Moryx.CommandCenter.Web/src/log/api/responses/AddAppenderResponse.ts b/src/Moryx.CommandCenter.Web/src/log/api/responses/AddAppenderResponse.ts deleted file mode 100644 index fce69f094..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/api/responses/AddAppenderResponse.ts +++ /dev/null @@ -1,3 +0,0 @@ -export default class AddAppenderResponse { - public appenderId: number; -} diff --git a/src/Moryx.CommandCenter.Web/src/log/components/LogMenuItemContent.tsx b/src/Moryx.CommandCenter.Web/src/log/components/LogMenuItemContent.tsx deleted file mode 100644 index ef0b54986..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/components/LogMenuItemContent.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ - -const TraceImg = require("../images/Trace.png"); -const DebugImg = require("../images/Debug.png"); -const InfoImg = require("../images/Info.png"); -const WarningImg = require("../images/Warning.png"); -const ErrorImg = require("../images/Error.png"); -const FatalImg = require("../images/Fatal.png"); -import * as React from "react"; -import LoggerModel from "../models/LoggerModel"; -import { LogLevel } from "../models/LogLevel"; - -interface LogMenuItemContentPropsModel { - Logger: LoggerModel; - onActiveLogLevelChange(e: React.FormEvent, l: LoggerModel): void; - onLabelClicked(l: LoggerModel): void; -} - -export default class LogMenuItemContent extends React.Component { - - public render(): React.ReactNode { - let img: any = TraceImg; - switch (this.props.Logger.activeLevel) { - case LogLevel.Trace: img = TraceImg; break; - case LogLevel.Debug: img = DebugImg; break; - case LogLevel.Info: img = InfoImg; break; - case LogLevel.Warning: img = WarningImg; break; - case LogLevel.Error: img = ErrorImg; break; - case LogLevel.Fatal: img = FatalImg; - } - - return ( -
- - ) => this.props.onLabelClicked(this.props.Logger)}> - {LoggerModel.shortLoggerName(this.props.Logger)} - -
- ); - } -} diff --git a/src/Moryx.CommandCenter.Web/src/log/components/Logger.tsx b/src/Moryx.CommandCenter.Web/src/log/components/Logger.tsx deleted file mode 100644 index 1b34747e3..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/components/Logger.tsx +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ - -import * as moment from "moment"; -import * as React from "react"; -import NotificationSystem = require("react-notification-system"); -import { Button, ButtonGroup, Col, Container, Input, Modal, ModalBody, ModalFooter, ModalHeader, Row, Table } from "reactstrap"; -import LogRestClient from "../api/LogRestClient"; -import LogLevelToCssClassConverter from "../converter/LogLevelToCssClassConverter"; -import LoggerModel from "../models/LoggerModel"; -import { LogLevel } from "../models/LogLevel"; -import LogMessageModel from "../models/LogMessageModel"; - -interface LogPropsModel { - RestClient: LogRestClient; - Logger: LoggerModel; - onCloseTab(logger: LoggerModel): void; -} - -interface LogStateModel { - LogMessages: LogMessageModel[]; - FilteredLogMessages: LogMessageModel[]; - AppenderId: number; - MaxLogEntries: number; - IntermediateMaxLogEntries: number; - FilterLogLevel: LogLevel; - SelectedLogMessage: LogMessageModel; - IsLogDetailDialogOpen: boolean; -} - -export default class Logger extends React.Component { - private updateLogMessagesTimer: NodeJS.Timeout; - - constructor(props: LogPropsModel) { - super(props); - this.state = { - LogMessages: [], - FilteredLogMessages: [], - AppenderId: -1, - MaxLogEntries: 20, - IntermediateMaxLogEntries: 20, - FilterLogLevel: LogLevel.Info, - SelectedLogMessage: null, - IsLogDetailDialogOpen: false, - }; - } - - public componentDidMount(): void { - this.props.RestClient.addRemoteAppender(this.props.Logger.name, this.props.Logger.activeLevel).then((data) => { - this.setState({ AppenderId: data.appenderId }); - this.onUpdateLogMessages(); - this.updateLogMessagesTimer = setInterval(this.onUpdateLogMessages.bind(this), 3000); - }); - } - - public componentWillUnmount(): void { - clearInterval(this.updateLogMessagesTimer); - if (this.state.AppenderId !== undefined) { - this.props.RestClient.removeRemoteAppender(this.state.AppenderId); - } - } - - public render(): React.ReactNode { - return ( -
- - - Filter by log level: - - ) => this.onFilterLogLevelChange(e)}> - - - - - - - - - Max. log entries: - - ) => this.onChangeMaxEntries(e)} - onBlur={this.onApplyMaxEntries.bind(this)} /> - - - - - - { this.props.onCloseTab != null && - - } - - - - - - - - - - - - - - - - { this.state.LogMessages.length !== 0 && ( - this.preRenderLogMessages() - )} - - { this.state.LogMessages.length === 0 && ( - - - - - - )} -
TimestampLevelMessageClass name
- No log messages found for this logger. -
- -
-
- { this.state.SelectedLogMessage != null && - - - Log message from {moment(this.state.SelectedLogMessage.timestamp).format("YYYY-MM-DD HH:mm:ss")} ({this.state.SelectedLogMessage.className}) - - - - - -
{this.state.SelectedLogMessage.message}
- -
-
-
- - - -
- } -
- ); - } - - private onUpdateLogMessages(): void { - this.props.RestClient.messages(this.state.AppenderId).then((data) => this.updateLogMessages(data)); - } - - private updateLogMessages(logMessages: LogMessageModel[]): void { - logMessages.reverse(); - const newLogMessageList = logMessages.concat(this.state.LogMessages); - this.setState({ LogMessages: newLogMessageList, FilteredLogMessages: Logger.applyFilter(newLogMessageList, this.state.FilterLogLevel, this.state.MaxLogEntries) }); - } - - private clearLogMessages(): void { - this.setState({ LogMessages: [], FilteredLogMessages: [] }); - } - - private onFilterLogLevelChange(e: React.FormEvent): void { - const newValue = (e.target as HTMLSelectElement).value as LogLevel; - this.setState({ FilterLogLevel: newValue, FilteredLogMessages: Logger.applyFilter(this.state.LogMessages, newValue, this.state.MaxLogEntries) }); - } - - private onChangeMaxEntries(e: React.FormEvent): void { - this.setState({ IntermediateMaxLogEntries: parseInt(e.currentTarget.value, 10) }); - } - - private onApplyMaxEntries(): void { - this.setState({ MaxLogEntries: this.state.IntermediateMaxLogEntries, FilteredLogMessages: Logger.applyFilter(this.state.LogMessages, this.state.FilterLogLevel, this.state.IntermediateMaxLogEntries) }); - } - - private static applyFilter(logMessages: LogMessageModel[], logLevel: LogLevel, maxEntries: number): LogMessageModel[] { - return logMessages.filter((logMessage: LogMessageModel) => logMessage.logLevel >= logLevel).slice(0, maxEntries); - } - - private onShowLogMessageDetailed(logMessage: LogMessageModel): void { - this.setState({ SelectedLogMessage: logMessage, IsLogDetailDialogOpen: true }); - } - - private static cutMessage(message: string): string { - const lines: string[] = message.split("\n"); - let cutted = lines.length > 0 ? lines[0] : message; - cutted = cutted.slice(0, 150); - - if (cutted.length < message.length) { - cutted += "..."; - } - - return cutted; - } - - private preRenderLogMessages(): React.ReactNode { - return this.state.FilteredLogMessages.map((message, idx) => - - {moment(message.timestamp).format("YYYY-MM-DD HH:mm:ss")} - {LogLevel[message.logLevel]} - {Logger.cutMessage(message.message)} - {message.className} - , - ); - } -} diff --git a/src/Moryx.CommandCenter.Web/src/log/container/Log.tsx b/src/Moryx.CommandCenter.Web/src/log/container/Log.tsx deleted file mode 100644 index 68d5a8fc3..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/container/Log.tsx +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ - -import { mdiFormatListBulletedSquare, mdiSquareEditOutline } from "@mdi/js"; -import Icon from "@mdi/react"; -import * as React from "react"; -import NotificationSystem = require("react-notification-system"); -import { connect } from "react-redux"; -import { Card, CardBody, CardHeader, Col, Container, Nav, NavItem, NavLink, Row, TabContent, TabPane } from "reactstrap"; -import TreeMenu from "../../common/components/Menu/TreeMenu"; -import MenuModel from "../../common/models/MenuModel"; -import { AppState } from "../../common/redux/AppState"; -import { ActionType } from "../../common/redux/Types"; -import LogRestClient from "../api/LogRestClient"; -import Logger from "../components/Logger"; -import LogMenuItemContent from "../components/LogMenuItemContent"; -import LoggerModel from "../models/LoggerModel"; -import { LogLevel } from "../models/LogLevel"; -import LogMenuItem from "../models/LogMenuItem"; -import { updateLoggers } from "../redux/LogActions"; - -interface LogPropsModel { - RestClient?: LogRestClient; - Loggers?: LoggerModel[]; - NotificationSystem?: NotificationSystem; -} - -interface LogDispatchPropModel { - onUpdateLoggers?(loggers: LoggerModel[]): void; -} - -const mapStateToProps = (state: AppState): LogPropsModel => { - return { - RestClient: state.Log.RestClient, - Loggers: state.Log.Loggers, - NotificationSystem: state.Common.NotificationSystem, - }; -}; - -const mapDispatchToProps = (dispatch: React.Dispatch>): LogDispatchPropModel => { - return { - onUpdateLoggers: (loggers: LoggerModel[]) => dispatch(updateLoggers(loggers)), - }; -}; - -interface LogStateModel { - ActiveTab: string; - Menu: MenuModel; - LoggerTabs: LoggerModel[]; -} - -class Log extends React.Component { - - private overviewLogger: LoggerModel; - - constructor(props: LogPropsModel & LogDispatchPropModel) { - super(props); - this.state = { ActiveTab: "0", Menu: { MenuItems: [] }, LoggerTabs: [] }; - - this.overviewLogger = new LoggerModel(); - this.overviewLogger.name = ""; - } - - public componentDidMount(): void { - this.props.RestClient.loggers().then((data) => { - this.props.onUpdateLoggers(data); - this.setState({Menu: { MenuItems: data.map((logger, idx) => this.createMenuItem(logger)) } }); - }); - } - - public createMenuItem(logger: LoggerModel): LogMenuItem { - const menuItem: LogMenuItem = { - Name: LoggerModel.shortLoggerName(logger), - NavPath: "/log", - Logger: logger, - SubMenuItems: logger.childLogger.map((childLogger, idx) => this.createMenuItem(childLogger)), - }; - - menuItem.Content = (); - return menuItem; - } - - private onActiveLogLevelChange(e: React.FormEvent, logger: LoggerModel): void { - e.preventDefault(); - - const newValue = (e.target as HTMLSelectElement).value as LogLevel; - this.props.RestClient.logLevel(logger.name, newValue).then((data) => { - if (data.success) { - logger.activeLevel = newValue; - Log.changeActiveLogLevel(logger, newValue); - this.forceUpdate(); - - this.props.NotificationSystem.addNotification({ title: "Success", message: "Log level for '" + logger.name + "' was set successfully", level: "success", autoDismiss: 5 }); - } else { - this.props.NotificationSystem.addNotification({ title: "Error", message: data.errorMessage, level: "error", autoDismiss: 5 }); - } - }); - } - - private static changeActiveLogLevel(logger: LoggerModel, logLevel: LogLevel): void { - if (logger.activeLevel > logLevel) { - logger.activeLevel = logLevel; - } - - for (const childLogger of logger.childLogger) { - Log.changeActiveLogLevel(childLogger, logLevel); - } - } - - private toggleTab(tabName: string): void { - this.setState({ActiveTab: tabName}); - } - - private onMenuItemClicked(logger: LoggerModel): void { - const idx = this.state.LoggerTabs.indexOf(logger); - if (idx === -1) { - this.setState((prevState) => ({ - LoggerTabs: [...prevState.LoggerTabs, logger], - ActiveTab: (prevState.LoggerTabs.length + 1).toString(), - })); - } else { - this.setState({ ActiveTab: (idx + 1).toString() }); - } - } - - private onCloseTab(logger: LoggerModel): void { - const idx = this.state.LoggerTabs.indexOf(logger); - if (idx !== -1) { - let activeTab = parseInt(this.state.ActiveTab, 10); - if (activeTab >= this.state.LoggerTabs.length) { - activeTab -= 1; - } - - this.setState((prevState) => ({ - LoggerTabs: prevState.LoggerTabs.filter((_, i) => i !== idx), - ActiveTab: (activeTab).toString(), - })); - } - } - - private preRenderNavForTabs(): React.ReactNode { - return this.state.LoggerTabs.map((logger, idx) => - - { this.toggleTab((idx + 1).toString()); }}> - {LoggerModel.shortLoggerName(logger)} - - , - ); - } - - private preRenderTabs(): React.ReactNode { - return this.state.LoggerTabs.map((logger, idx) => - - - - - - - , - ); - } - - public render(): React.ReactNode { - return ( - - - - - - Loggers - - - - - - - - - - - - - Log - - - - - - - - - - - - {this.preRenderTabs()} - - - - - - ); - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(Log); diff --git a/src/Moryx.CommandCenter.Web/src/log/converter/LogLevelToCssClassConverter.ts b/src/Moryx.CommandCenter.Web/src/log/converter/LogLevelToCssClassConverter.ts deleted file mode 100644 index c1ea9d685..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/converter/LogLevelToCssClassConverter.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ -import { LogLevel } from "../models/LogLevel"; - -export default class LogLevelToCssClassConverter { - public static Convert(logLevel: LogLevel): string { - switch (logLevel) { - case LogLevel.Trace: { - return "#e9e9e9"; - } - case LogLevel.Debug: { - return "#d9d9d9"; - } - case LogLevel.Info: { - return "white"; - } - case LogLevel.Warning: { - return "#ffffcc"; - } - case LogLevel.Error: { - return "#ffe6e6"; - } - case LogLevel.Fatal: { - return "#ff3333"; - } - default: { - return "white"; - } - } - } -} diff --git a/src/Moryx.CommandCenter.Web/src/log/images/Debug.png b/src/Moryx.CommandCenter.Web/src/log/images/Debug.png deleted file mode 100644 index 2cc5dc81b..000000000 Binary files a/src/Moryx.CommandCenter.Web/src/log/images/Debug.png and /dev/null differ diff --git a/src/Moryx.CommandCenter.Web/src/log/images/Error.png b/src/Moryx.CommandCenter.Web/src/log/images/Error.png deleted file mode 100644 index f9476adf7..000000000 Binary files a/src/Moryx.CommandCenter.Web/src/log/images/Error.png and /dev/null differ diff --git a/src/Moryx.CommandCenter.Web/src/log/images/Fatal.png b/src/Moryx.CommandCenter.Web/src/log/images/Fatal.png deleted file mode 100644 index 221c3d165..000000000 Binary files a/src/Moryx.CommandCenter.Web/src/log/images/Fatal.png and /dev/null differ diff --git a/src/Moryx.CommandCenter.Web/src/log/images/Info.png b/src/Moryx.CommandCenter.Web/src/log/images/Info.png deleted file mode 100644 index 573e36ed0..000000000 Binary files a/src/Moryx.CommandCenter.Web/src/log/images/Info.png and /dev/null differ diff --git a/src/Moryx.CommandCenter.Web/src/log/images/Trace.png b/src/Moryx.CommandCenter.Web/src/log/images/Trace.png deleted file mode 100644 index d3a1cc8f4..000000000 Binary files a/src/Moryx.CommandCenter.Web/src/log/images/Trace.png and /dev/null differ diff --git a/src/Moryx.CommandCenter.Web/src/log/images/Warning.png b/src/Moryx.CommandCenter.Web/src/log/images/Warning.png deleted file mode 100644 index 132bbd283..000000000 Binary files a/src/Moryx.CommandCenter.Web/src/log/images/Warning.png and /dev/null differ diff --git a/src/Moryx.CommandCenter.Web/src/log/models/LogLevel.ts b/src/Moryx.CommandCenter.Web/src/log/models/LogLevel.ts deleted file mode 100644 index b762d7c91..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/models/LogLevel.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ -export enum LogLevel { - Trace = "Trace", - Debug = "Debug", - Info = "Info", - Warning = "Warning", - Error = "Error", - Fatal = "Fatal", -} diff --git a/src/Moryx.CommandCenter.Web/src/log/models/LogMenuItem.ts b/src/Moryx.CommandCenter.Web/src/log/models/LogMenuItem.ts deleted file mode 100644 index bb360b792..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/models/LogMenuItem.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ -import MenuItemModel from "../../common/models/MenuItemModel"; -import LoggerModel from "./LoggerModel"; - -export default interface LogMenuItem extends MenuItemModel { - Logger: LoggerModel; -} diff --git a/src/Moryx.CommandCenter.Web/src/log/models/LogMessageModel.ts b/src/Moryx.CommandCenter.Web/src/log/models/LogMessageModel.ts deleted file mode 100644 index aa246ac82..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/models/LogMessageModel.ts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ -import LoggerModel from "./LoggerModel"; -import { LogLevel } from "./LogLevel"; - -export default class LogMessageModel { - public logger: LoggerModel; - public className: string; - public logLevel: LogLevel; - public message: string; - public timestamp: Date; -} diff --git a/src/Moryx.CommandCenter.Web/src/log/models/LoggerModel.ts b/src/Moryx.CommandCenter.Web/src/log/models/LoggerModel.ts deleted file mode 100644 index ddcdd52cf..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/models/LoggerModel.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ -import { LogLevel } from "./LogLevel"; - -export default class LoggerModel { - public name: string; - public activeLevel: LogLevel; - public childLogger: LoggerModel[]; - public parent: LoggerModel; - - public static shortLoggerName(logger: LoggerModel): string { - const splittedLoggerPath = logger.name.split("."); - return splittedLoggerPath[splittedLoggerPath.length - 1]; - } -} diff --git a/src/Moryx.CommandCenter.Web/src/log/redux/LogActions.ts b/src/Moryx.CommandCenter.Web/src/log/redux/LogActions.ts deleted file mode 100644 index 2338993e8..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/redux/LogActions.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ -import { ActionType } from "../../common/redux/Types"; -import LoggerModel from "../models/LoggerModel"; - -export const UPDATE_LOGGERS = "UPDATE_LOGGERS"; - -export function updateLoggers(loggers: LoggerModel[]): ActionType { - return { type: UPDATE_LOGGERS, payload: loggers }; -} diff --git a/src/Moryx.CommandCenter.Web/src/log/redux/LogState.ts b/src/Moryx.CommandCenter.Web/src/log/redux/LogState.ts deleted file mode 100644 index 6269e2d95..000000000 --- a/src/Moryx.CommandCenter.Web/src/log/redux/LogState.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2020, Phoenix Contact GmbH & Co. KG - * Licensed under the Apache License, Version 2.0 -*/ -require("../../types/constants"); -import { ActionType } from "../../common/redux/Types"; -import LogRestClient from "../api/LogRestClient"; -import LoggerModel from "../models/LoggerModel"; -import { UPDATE_LOGGERS } from "./LogActions"; - -export interface LogState { - RestClient: LogRestClient; - Loggers: LoggerModel[]; -} - -export const initialLogState: LogState = { - Loggers: [], - RestClient: new LogRestClient(BASE_URL), -}; - -export function getLogReducer(state: LogState = initialLogState, action: ActionType<{}>): LogState { - switch (action.type) { - case UPDATE_LOGGERS: { - return { ...state, Loggers: action.payload as LoggerModel[] }; - } - } - return state; -} diff --git a/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/BooleanEditor.tsx b/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/BooleanEditor.tsx index 62fcdca20..008a96ed4 100644 --- a/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/BooleanEditor.tsx +++ b/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/BooleanEditor.tsx @@ -3,7 +3,7 @@ * Licensed under the Apache License, Version 2.0 */ -import "bootstrap-toggle/css/bootstrap2-toggle.css"; +import "bootstrap5-toggle/css/bootstrap5-toggle.css"; import * as React from "react"; import BootstrapToggle from "react-bootstrap-toggle"; import { Input } from "reactstrap"; @@ -13,15 +13,15 @@ import InputEditorBase, { InputEditorBasePropModel } from "./InputEditorBase"; export default class ByteEditor extends InputEditorBase { constructor(props: InputEditorBasePropModel) { super(props); - this.state = { }; + this.state = {}; } public render(): React.ReactNode { return ( ) => this.onToggle(e)} - height="35px" /> + disabled={this.props.Entry.value.isReadOnly || this.props.IsReadOnly} + onClick={(e: React.MouseEvent) => this.onToggle(e)} + height="35px" /> ); } diff --git a/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/CollapsibleEntryEditorBase.tsx b/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/CollapsibleEntryEditorBase.tsx index 33bd853a1..04d76e007 100644 --- a/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/CollapsibleEntryEditorBase.tsx +++ b/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/CollapsibleEntryEditorBase.tsx @@ -7,7 +7,7 @@ import * as React from "react"; import { Collapse } from "reactstrap"; import Entry from "../../models/Entry"; -export interface CollapsibleEntryEditorBasePropModel { +export interface CollapsibleEntryEditorBasePropModel extends React.PropsWithChildren { Entry: Entry; IsExpanded: boolean; IsReadOnly: boolean; diff --git a/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/NavigableConfigEditor.tsx b/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/NavigableConfigEditor.tsx index f3737f0c0..651d56cc8 100644 --- a/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/NavigableConfigEditor.tsx +++ b/src/Moryx.CommandCenter.Web/src/modules/components/ConfigEditor/NavigableConfigEditor.tsx @@ -4,7 +4,7 @@ */ import { Action, History, Location, UnregisterCallback } from "history"; -import * as qs from "query-string"; +import queryString from "query-string"; import * as React from "react"; import { Button, ButtonGroup, Col, Container, Row } from "reactstrap"; import Entry from "../../models/Entry"; @@ -42,7 +42,7 @@ export default class NavigableConfigEditor extends React.ComponentValue
+ Entries={this.state.Entries} + Root={this.props.Root} + navigateToEntry={this.navigateToEntry.bind(this)} + IsReadOnly={this.props.IsReadOnly} />
); diff --git a/src/Moryx.CommandCenter.Web/src/modules/container/Module.tsx b/src/Moryx.CommandCenter.Web/src/modules/container/Module.tsx index e0273dab5..21815347b 100644 --- a/src/Moryx.CommandCenter.Web/src/modules/container/Module.tsx +++ b/src/Moryx.CommandCenter.Web/src/modules/container/Module.tsx @@ -3,7 +3,7 @@ * Licensed under the Apache License, Version 2.0 */ -import { mdiCheck, mdiDatabase, mdiHexagon, mdiHexagonMultiple, mdiPlay, mdiRestart, mdiStop} from "@mdi/js"; +import { mdiCheck, mdiDatabase, mdiHexagon, mdiHexagonMultiple, mdiPlay, mdiRestart, mdiStop } from "@mdi/js"; import Icon from "@mdi/react"; import * as React from "react"; import { connect } from "react-redux"; @@ -53,8 +53,8 @@ class Module extends React.Component +
Type @@ -182,10 +182,10 @@ class Module extends React.Component { this.props.Module.dependencies.map((module, idx) => - - {module.name} - - ) + + {module.name} + + ) } @@ -200,7 +200,7 @@ class Module extends React.ComponentStart behaviour: ) => this.onStartBehaviourChange(e)}> + onChange={(e: React.FormEvent) => this.onStartBehaviourChange(e)}> @@ -211,7 +211,7 @@ class Module extends React.ComponentFailure behaviour: ) => this.onFailureBehaviourChange(e)}> + onChange={(e: React.FormEvent) => this.onFailureBehaviourChange(e)}> @@ -235,20 +235,20 @@ class Module extends React.Component - { - this.props.Module.notifications.map((notification, idx) => - ) => this.openNotificationDetailsDialog(e, notification)}> - {notification.exception != null ? notification.exception.exceptionTypeName : "-"} - {notification.message} - - - {Serverity[notification.severity]} - - - , - ) - } + { + this.props.Module.notifications.map((notification, idx) => + ) => this.openNotificationDetailsDialog(e, notification)}> + {notification.exception != null ? notification.exception.exceptionTypeName : "-"} + {notification.message} + + + {Serverity[notification.severity]} + + + , + ) + } )} @@ -262,9 +262,9 @@ class Module extends React.Component - + - {this.state.SelectedNotification.message} + {this.state.SelectedNotification.message} @@ -285,14 +285,14 @@ class Module extends React.Component - { this.state.SelectedNotification.exception.innerException == null ? ( + {this.state.SelectedNotification.exception.innerException == null ? ( No inner exception found. ) : ( Inner exception )} - { this.state.SelectedNotification.exception.innerException != null && + {this.state.SelectedNotification.exception.innerException != null && {Module.preRenderInnerException(this.state.SelectedNotification.exception.innerException)} diff --git a/src/Moryx.CommandCenter.Web/src/modules/container/ModuleConfiguration.tsx b/src/Moryx.CommandCenter.Web/src/modules/container/ModuleConfiguration.tsx index e8abf6177..10582bc5f 100644 --- a/src/Moryx.CommandCenter.Web/src/modules/container/ModuleConfiguration.tsx +++ b/src/Moryx.CommandCenter.Web/src/modules/container/ModuleConfiguration.tsx @@ -3,13 +3,12 @@ * Licensed under the Apache License, Version 2.0 */ -import { mdiCogs, mdiContentSave, mdiHexagon, mdiSync, mdiUndo} from "@mdi/js"; +import { mdiCogs, mdiContentSave, mdiHexagon, mdiSync, mdiUndo } from "@mdi/js"; import Icon from "@mdi/react"; import * as React from "react"; -import NotificationSystem = require("react-notification-system"); import { RouteComponentProps, withRouter } from "react-router-dom"; -import { Button, ButtonGroup, Card, CardBody, CardHeader, Col, Container, ListGroup, Row } from "reactstrap"; -import ListGroupItem from "reactstrap/lib/ListGroupItem"; +import { toast, ToastContainer } from "react-toastify"; +import { Button, ButtonGroup, Card, CardBody, CardHeader, Col, Container, ListGroup, ListGroupItem, Row } from "reactstrap"; import ModuleHeader from "../../common/components/ModuleHeader"; import ModulesRestClient from "../api/ModulesRestClient"; import NavigableConfigEditor from "../components/ConfigEditor/NavigableConfigEditor"; @@ -20,7 +19,6 @@ import Entry from "../models/Entry"; interface ModuleConfigurationPropModel { RestClient?: ModulesRestClient; ModuleName: string; - NotificationSystem: NotificationSystem; } interface ModuleConfigurationStateModel { @@ -52,33 +50,33 @@ class ModuleConfiguration extends React.Component { return this.props.RestClient.moduleConfig(this.props.ModuleName) - .then((data) => { - Config.patchConfig(data); - this.setState( - { - ModuleConfig: data, - ParentEntry: data.root, - CurrentSubEntries: data.root.subEntries, - ConfigIsLoading: false, - }); - }); + .then((data) => { + Config.patchConfig(data); + this.setState( + { + ModuleConfig: data, + ParentEntry: data.root, + CurrentSubEntries: data.root.subEntries, + ConfigIsLoading: false, + }); + }); } public onApply(): void { this.props.RestClient.saveModuleConfig(this.props.ModuleName, { Config: this.state.ModuleConfig, UpdateMode: ConfigUpdateMode.SaveAndReincarnate }) - .then((result) => this.props.NotificationSystem.addNotification({ title: "Saved", message: "Configuration was saved successfully. Module is restarting...", level: "success", autoDismiss: 5 })); + .then((result) => toast.success("Configuration was saved successfully. Module is restarting...", { autoClose: 5000 })); } public onSave(): void { this.props.RestClient.saveModuleConfig(this.props.ModuleName, { Config: this.state.ModuleConfig, UpdateMode: ConfigUpdateMode.OnlySave }) - .then((result) => this.props.NotificationSystem.addNotification({ title: "Saved", message: "Configuration was saved successfully", level: "success", autoDismiss: 5 })); + .then((result) => toast.success("Configuration was saved successfully", { autoClose: 5000 })); } public onRevert(): void { this.props.history.push("?"); this.setState({ ConfigIsLoading: true }); this.loadConfig() - .then((result) => this.props.NotificationSystem.addNotification({ title: "Reverted", message: "Configuration was reverted", level: "success", autoDismiss: 3 })); + .then((result) => toast.success("Configuration was reverted", { autoClose: 3000 })); } public render(): React.ReactNode { @@ -98,11 +96,11 @@ class ModuleConfiguration extends React.ComponentLoading config ... } + Entries={this.state.CurrentSubEntries} + Root={this.state.ModuleConfig.root} + IsReadOnly={false} + History={this.props.history} + Location={this.props.location} />