Skip to content

Commit

Permalink
Update react-router-dom from 5.3.4 to 6.22.0
Browse files Browse the repository at this point in the history
This migration requires turning class components into functional ones. Also removes `history` package.
  • Loading branch information
jsonBackup committed Feb 23, 2024
1 parent 4411531 commit 1fd2adc
Show file tree
Hide file tree
Showing 15 changed files with 356 additions and 446 deletions.
5 changes: 2 additions & 3 deletions src/Moryx.CommandCenter.Web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,14 @@
"@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-dom": "18.2.0",
"react-redux": "^9.1.0",
"react-router": "^5.3.4",
"react-router-dom": "^5.3.4",
"react-router": "^6.22.0",
"react-router-dom": "^6.22.0",
"react-router-redux": "^4.0.8",
"react-toastify": "^10.0.4",
"reactstrap": "^8.10.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,35 @@
*/

import * as React from "react";
import { Link, RouteComponentProps, withRouter } from "react-router-dom";
import { Collapse } from "reactstrap";
import { useNavigate } from "react-router-dom";
import MenuItemModel from "../../models/MenuItemModel";
import MenuModel from "../../models/MenuModel";
import RoutingMenuItem from "./RoutingMenuItem";
import { MenuProps } from "./TreeMenu";

class RoutingMenu extends React.Component<RouteComponentProps<{}> & MenuProps, {}> {
function RoutingMenu(props: MenuProps) {
const navigate = useNavigate();

constructor(props: RouteComponentProps<{}> & MenuProps) {
super (props);
this.state = {};
}

protected handleMenuItemClick(menuItem: MenuItemModel): void {
if (this.props.onActiveMenuItemChanged != null) {
this.props.onActiveMenuItemChanged(menuItem);
const handleMenuItemClick = (menuItem: MenuItemModel): void => {
if (props.onActiveMenuItemChanged != null) {
props.onActiveMenuItemChanged(menuItem);
}
this.props.history.push(menuItem.NavPath);
}
navigate(menuItem.NavPath);
};

protected renderMenu(menuItems: MenuItemModel[]): React.ReactNode {
return menuItems.map ((menuItem, idx) => {
const renderMenu = (menuItems: MenuItemModel[]): React.ReactNode => {
return menuItems.map((menuItem, idx) => {
return (
<RoutingMenuItem key={idx} MenuItem={menuItem} Level={0} onMenuItemClicked={(menuItem) => this.handleMenuItemClick(menuItem)} />
<RoutingMenuItem
key={idx}
MenuItem={menuItem}
Level={0}
onMenuItemClicked={(menuItem) => handleMenuItemClick(menuItem)}
/>
);
});
}
};

public render(): React.ReactNode {
return (
<div>
{this.renderMenu(this.props.Menu.MenuItems)}
</div>
);
}
return <div>{renderMenu(props.Menu.MenuItems)}</div>;
}

export default withRouter<RouteComponentProps<{}> & MenuProps, React.ComponentType<any>>(RoutingMenu);
export default RoutingMenu;
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
/*
* Copyright (c) 2020, Phoenix Contact GmbH & Co. KG
* Licensed under the Apache License, Version 2.0
* Copyright (c) 2020, Phoenix Contact GmbH & Co. KG
* Licensed under the Apache License, Version 2.0
*/

import { Location, UnregisterCallback } from "history";
import * as React from "react";
import { Link, RouteComponentProps, withRouter } from "react-router-dom";
import { Link, Location, useLocation, useNavigate } from "react-router-dom";
import { ListGroupItem } from "reactstrap";
import MenuItemModel from "../../models/MenuItemModel";

Expand All @@ -19,54 +18,42 @@ interface MenuItemState {
IsOpened: boolean;
}

class RoutingMenuItem extends React.Component<RouteComponentProps<{}> & MenuItemProps, MenuItemState> {
private unregisterListenerCallback: UnregisterCallback;
function RoutingMenuItem(props: MenuItemProps) {
const location = useLocation();
const navigate = useNavigate();

constructor(props: RouteComponentProps<{}> & MenuItemProps) {
super(props);
this.state = { IsOpened: this.isOpened(this.props.location) };
const isOpened = (location: Location): boolean => {
return location.pathname.startsWith(props.MenuItem.NavPath);
};

this.unregisterListenerCallback = this.props.history.listen(this.onRouteChanged.bind(this));
this.onMenuItemClicked = this.onMenuItemClicked.bind(this);
}
const [IsOpened, setIsOpened] = React.useState<boolean>(isOpened(location));

public componentWillUnmount(): void {
this.unregisterListenerCallback();
}
React.useEffect(() => {
setIsOpened(isOpened(location));
}, [navigate]);

private isOpened(location: Location): boolean {
return location.pathname.startsWith(this.props.MenuItem.NavPath);
}

private onRouteChanged(location: Location, action: string): void {
this.setState({ IsOpened: this.isOpened(location) });
}

private handleMenuItemClick(e: React.MouseEvent<HTMLElement>): void {
const handleMenuItemClick = (e: React.MouseEvent<HTMLElement>): void => {
e.preventDefault();
setIsOpened((prevState) => !prevState);
onMenuItemClicked(props.MenuItem);
};

this.setState((prevState) => ({ IsOpened: !prevState.IsOpened }));
this.onMenuItemClicked(this.props.MenuItem);
}

private onMenuItemClicked(menuItem: MenuItemModel): void {
if (this.props.onMenuItemClicked != null) {
this.props.onMenuItemClicked(menuItem);
const onMenuItemClicked = (menuItem: MenuItemModel): void => {
if (props.onMenuItemClicked != null) {
props.onMenuItemClicked(menuItem);
}
}

public render(): React.ReactNode {
const isActive = this.props.location.pathname.includes(this.props.MenuItem.NavPath);

return (
<ListGroupItem active={isActive} className="menu-item" onClick={(e: React.MouseEvent<HTMLElement>) => this.handleMenuItemClick(e)}>
<Link to={this.props.MenuItem.NavPath}>
{this.props.MenuItem.Name}
</Link>
{this.props.MenuItem.Content}
</ListGroupItem >
);
}
};

const isActive = isOpened(location);

return (
<ListGroupItem active={isActive} className="menu-item" onClick={(e: React.MouseEvent<HTMLElement>) => handleMenuItemClick(e)}>
<Link to={props.MenuItem.NavPath}>
{props.MenuItem.Name}
</Link>
{props.MenuItem.Content}
</ListGroupItem>
);
}

export default withRouter<RouteComponentProps<{}> & MenuItemProps, React.ComponentType<any>>(RoutingMenuItem);
export default RoutingMenuItem;
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import { mdiChevronDown, mdiChevronUp } from "@mdi/js";
import Icon from "@mdi/react";
import * as React from "react";
import { Link, RouteComponentProps, withRouter } from "react-router-dom";
import { Col, Collapse, Container, Row } from "reactstrap";
import MenuItemModel, { IconType } from "../../models/MenuItemModel";

Expand All @@ -22,7 +21,7 @@ interface MenuItemState {

export default class TreeMenuItem extends React.Component<MenuItemProps, MenuItemState> {
constructor(props: MenuItemProps) {
super (props);
super(props);
this.state = { IsOpened: false };

this.onMenuItemClicked = this.onMenuItemClicked.bind(this);
Expand All @@ -42,47 +41,47 @@ export default class TreeMenuItem extends React.Component<MenuItemProps, MenuIte
}

private renderSubMenuItems(): React.ReactNode {
return this.props.MenuItem.SubMenuItems.map ((menuItem, idx) =>
return this.props.MenuItem.SubMenuItems.map((menuItem, idx) =>
<TreeMenuItem key={idx}
MenuItem={menuItem}
Level={this.props.Level + 1}
onMenuItemClicked={this.onMenuItemClicked}
/>);
MenuItem={menuItem}
Level={this.props.Level + 1}
onMenuItemClicked={this.onMenuItemClicked}
/>);
}

public render(): React.ReactNode {
const hasSubItems = this.props.MenuItem.SubMenuItems.length > 0;
const iconType = this.props.MenuItem.IconType == undefined ? IconType.Icon : IconType.Image;
const defaultContent = (
<div>
{ this.props.MenuItem.Icon !== undefined && iconType === IconType.Icon &&
{this.props.MenuItem.Icon !== undefined && iconType === IconType.Icon &&
<Icon path={this.props.MenuItem.Icon} className="icon right-space" />
}
{ this.props.MenuItem.Icon !== undefined && iconType === IconType.Image &&
<img src={this.props.MenuItem.Icon} style={{marginRight: "4px"}} />
{this.props.MenuItem.Icon !== undefined && iconType === IconType.Image &&
<img src={this.props.MenuItem.Icon} style={{ marginRight: "4px" }} />
}
<Icon path={this.props.MenuItem.Icon} className="icon right-sapce" />
<span style={{wordBreak: "break-all"}}>{this.props.MenuItem.Name}</span>
<span style={{ wordBreak: "break-all" }}>{this.props.MenuItem.Name}</span>
</div>
);

return (
<div style={{paddingLeft: this.props.Level * 10 + "px", margin: "5px 0px 5px 0px"}}>
<div style={{ paddingLeft: this.props.Level * 10 + "px", margin: "5px 0px 5px 0px" }}>
<Container fluid={true} className="menu-item">
<Row>
<Col md={10}>
<div>
{ this.props.MenuItem.Content === undefined &&
{this.props.MenuItem.Content === undefined &&
defaultContent
}
{ this.props.MenuItem.Content !== undefined &&
{this.props.MenuItem.Content !== undefined &&
this.props.MenuItem.Content
}
</div>
</Col>
<Col md={2} onClick={(e: React.MouseEvent<HTMLElement>) => this.handleMenuItemClick(e)}>
{ hasSubItems &&
<Icon path={this.state.IsOpened ? mdiChevronUp : mdiChevronDown} className="icon"/>
{hasSubItems &&
<Icon path={this.state.IsOpened ? mdiChevronUp : mdiChevronDown} className="icon" />
}
</Col>
</Row>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export class ModuleHeader extends React.Component<ModulePropModel & ModuleDispat
<Navbar className="navbar-default" expand="md">
<Nav className="navbar-left" navbar={true}>
<NavItem>
<NavLink exact={true} to={`/modules/${this.props.ModuleName}`} className="navbar-nav-link">
<NavLink end={true} to={`/modules/${this.props.ModuleName}`} className="navbar-nav-link">
<Icon path={mdiMonitor} className="icon right-space" />
Overview
</NavLink>
Expand All @@ -61,7 +61,7 @@ export class ModuleHeader extends React.Component<ModulePropModel & ModuleDispat
</NavItem>
<NavItem >
<NavLink to={`/modules/${this.props.ModuleName}/console`} className="navbar-nav-link">
<Icon path={mdiConsoleLine}className="icon right-space" />
<Icon path={mdiConsoleLine} className="icon right-space" />
Console
</NavLink>
</NavItem>
Expand Down
84 changes: 37 additions & 47 deletions src/Moryx.CommandCenter.Web/src/common/container/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

import * as React from "react";
import { connect } from "react-redux";
import { Redirect, Route, RouteComponentProps, Switch, withRouter } from "react-router-dom";
import { toast, ToastContainer } from "react-toastify";
import { Navigate, Route, Routes } from "react-router-dom";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { Container } from "reactstrap";
import DatabasesRestClient from "../../databases/api/DatabasesRestClient";
Expand Down Expand Up @@ -71,56 +71,46 @@ const mapDispatchToProps = (dispatch: React.Dispatch<ActionType<{}>>): AppDispat
};
};

class App extends React.Component<AppPropModel & RouteComponentProps<{}> & AppDispatchPropModel> {
private updateClockTimer: NodeJS.Timeout;
private updateLoadAndModulesTimer: NodeJS.Timeout;
function App(props: AppPropModel & AppDispatchPropModel) {
const updateClockTimerRef = React.useRef<NodeJS.Timeout>();
const updateLoadAndModulesTimerRef = React.useRef<NodeJS.Timeout>();

constructor(props: AppPropModel & RouteComponentProps<{}> & AppDispatchPropModel) {
super(props);
React.useEffect(() => {
updateLoadAndModulesTimerRef.current = setInterval(loadAndModulesUpdater, 5000);
props.ModulesRestClient.modules().then((data) => props?.onUpdateModules(data));

this.loadAndModulesUpdater = this.loadAndModulesUpdater.bind(this);
}
return () => {
clearInterval(updateClockTimerRef.current!);
clearInterval(updateLoadAndModulesTimerRef.current!);
};
}, []);

public componentDidMount(): void {
this.updateLoadAndModulesTimer = setInterval(this.loadAndModulesUpdater, 5000);
this.props.ModulesRestClient.modules().then((data) => this.props?.onUpdateModules(data));
}

public componentWillUnmount(): void {
clearInterval(this.updateClockTimer);
clearInterval(this.updateLoadAndModulesTimer);
}

public render(): React.ReactNode {
return (
<div className="commandcenter-app-container">
<div className="commandcenter-content-wrapper">
<ToastContainer />

<Container fluid={true} id="body" className="content">
<Switch>
<Route path="/modules" component={Modules} />
<Route path="/databases" component={Databases} />
<Route render={() => <Redirect to="/databases" />} />
</Switch>
</Container>
</div>
</div>
);
}

private loadAndModulesUpdater(): void {
this.props.Modules.forEach((module) => {
this.props.ModulesRestClient.healthState(module.name).then((data) =>
this.props.onUpdateModuleHealthState(module.name, data)
const loadAndModulesUpdater = (): void => {
props.Modules.forEach((module) => {
props.ModulesRestClient.healthState(module.name).then((data) =>
props.onUpdateModuleHealthState(module.name, data)
);
this.props.ModulesRestClient.notifications(module.name).then((data) =>
this.props.onUpdateModuleNotifications(module.name, data)
props.ModulesRestClient.notifications(module.name).then((data) =>
props.onUpdateModuleNotifications(module.name, data)
);
});
}
};

return (
<div className="commandcenter-app-container">
<div className="commandcenter-content-wrapper">
<ToastContainer />

<Container fluid={true} id="body" className="content">
<Routes>
<Route path="/modules/*" element={<Modules />} />
<Route path="/databases/*" element={<Databases />} />
<Route path="*" element={<Navigate to="/databases/*" />} />
</Routes>
</Container>
</div>
</div>
);
}

export default withRouter<RouteComponentProps<{}>, React.ComponentType<any>>(
connect<AppPropModel, AppDispatchPropModel>(mapStateToProps, mapDispatchToProps)(App)
);
export default connect(mapStateToProps, mapDispatchToProps)(App);
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@
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 { connect, Provider } from "react-redux";
import { RouteComponentProps, withRouter } from "react-router-dom";
import { toast, ToastContainer } from "react-toastify";
import { connect } from "react-redux";
import { toast } 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";
Expand Down
Loading

0 comments on commit 1fd2adc

Please sign in to comment.