update navigation for react-router v6

This commit is contained in:
Min RK
2024-03-08 14:26:41 +01:00
parent bfe143f1ac
commit 77e625d36d
11 changed files with 82 additions and 115 deletions

View File

@@ -1,15 +1,16 @@
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
const AddUser = (props) => {
var [users, setUsers] = useState([]),
const [users, setUsers] = useState([]),
[admin, setAdmin] = useState(false),
[errorAlert, setErrorAlert] = useState(null),
limit = useSelector((state) => state.limit);
var dispatch = useDispatch();
const dispatch = useDispatch();
const navigate = useNavigate();
var dispatchPageChange = (data, page) => {
dispatch({
@@ -21,7 +22,7 @@ const AddUser = (props) => {
});
};
var { addUsers, updateUsers, history } = props;
var { addUsers, updateUsers } = props;
return (
<>
@@ -96,7 +97,7 @@ const AddUser = (props) => {
data.status < 300
? updateUsers(0, limit)
.then((data) => dispatchPageChange(data, 0))
.then(() => history.push("/"))
.then(() => navigate("/"))
.catch(() =>
setErrorAlert(`Failed to update users.`),
)
@@ -123,9 +124,6 @@ const AddUser = (props) => {
AddUser.propTypes = {
addUsers: PropTypes.func,
updateUsers: PropTypes.func,
history: PropTypes.shape({
push: PropTypes.func,
}),
};
export default AddUser;

View File

@@ -26,11 +26,7 @@ var mockAsyncRejection = () =>
var addUserJsx = (spy, spy2, spy3) => (
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<AddUser
addUsers={spy}
updateUsers={spy3 || spy2 || spy}
history={{ push: () => {} }}
/>
<AddUser addUsers={spy} updateUsers={spy3 || spy2 || spy} />
</HashRouter>
</Provider>
);

View File

@@ -1,16 +1,17 @@
import React, { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import PropTypes from "prop-types";
const CreateGroup = (props) => {
var [groupName, setGroupName] = useState(""),
const [groupName, setGroupName] = useState(""),
[errorAlert, setErrorAlert] = useState(null),
limit = useSelector((state) => state.limit);
var dispatch = useDispatch();
const dispatch = useDispatch();
const navigate = useNavigate();
var dispatchPageUpdate = (data, page) => {
const dispatchPageUpdate = (data, page) => {
dispatch({
type: "GROUPS_PAGE",
value: {
@@ -20,7 +21,7 @@ const CreateGroup = (props) => {
});
};
var { createGroup, updateGroups, history } = props;
const { createGroup, updateGroups } = props;
return (
<>
@@ -79,7 +80,7 @@ const CreateGroup = (props) => {
return data.status < 300
? updateGroups(0, limit)
.then((data) => dispatchPageUpdate(data, 0))
.then(() => history.push("/groups"))
.then(() => navigate("/groups"))
.catch(() =>
setErrorAlert(`Could not update groups list.`),
)
@@ -108,9 +109,6 @@ const CreateGroup = (props) => {
CreateGroup.propTypes = {
createGroup: PropTypes.func,
updateGroups: PropTypes.func,
history: PropTypes.shape({
push: PropTypes.func,
}),
};
export default CreateGroup;

View File

@@ -25,11 +25,7 @@ var mockAsyncRejection = () =>
var createGroupJsx = (callbackSpy) => (
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<CreateGroup
createGroup={callbackSpy}
updateGroups={callbackSpy}
history={{ push: () => {} }}
/>
<CreateGroup createGroup={callbackSpy} updateGroups={callbackSpy} />
</HashRouter>
</Provider>
);

View File

@@ -1,13 +1,15 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import { Link, useLocation, useNavigate } from "react-router-dom";
const EditUser = (props) => {
var limit = useSelector((state) => state.limit),
const limit = useSelector((state) => state.limit),
[errorAlert, setErrorAlert] = useState(null);
var dispatch = useDispatch();
const dispatch = useDispatch();
const location = useLocation();
const navigate = useNavigate();
var dispatchPageChange = (data, page) => {
dispatch({
@@ -19,14 +21,19 @@ const EditUser = (props) => {
});
};
var { editUser, deleteUser, noChangeEvent, updateUsers, history } = props;
var { editUser, deleteUser, noChangeEvent, updateUsers } = props;
if (props.location.state == undefined) {
props.history.push("/");
return <></>;
useEffect(() => {
if (!location.state) {
navigate("/");
}
}, [location]);
if (!location.state) {
return null;
}
var { username, has_admin } = props.location.state;
var { username, has_admin } = location.state;
var [updatedUsername, setUpdatedUsername] = useState(""),
[admin, setAdmin] = useState(has_admin);
@@ -93,7 +100,7 @@ const EditUser = (props) => {
data.status < 300
? updateUsers(0, limit)
.then((data) => dispatchPageChange(data, 0))
.then(() => history.push("/"))
.then(() => navigate("/"))
.catch(() =>
setErrorAlert(
`Could not update users list.`,
@@ -135,7 +142,7 @@ const EditUser = (props) => {
data.status < 300
? updateUsers(0, limit)
.then((data) => dispatchPageChange(data, 0))
.then(() => history.push("/"))
.then(() => navigate("/"))
.catch(() =>
setErrorAlert(`Could not update users list.`),
)
@@ -159,15 +166,6 @@ const EditUser = (props) => {
};
EditUser.propTypes = {
location: PropTypes.shape({
state: PropTypes.shape({
username: PropTypes.string,
has_admin: PropTypes.bool,
}),
}),
history: PropTypes.shape({
push: PropTypes.func,
}),
editUser: PropTypes.func,
deleteUser: PropTypes.func,
noChangeEvent: PropTypes.func,

View File

@@ -16,6 +16,14 @@ jest.mock("react-redux", () => ({
useSelector: jest.fn(),
}));
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useLocation: jest.fn().mockImplementation(() => {
return { state: { username: "foo", has_admin: false } };
}),
useNavigate: jest.fn(),
}));
var mockAsync = (data) =>
jest.fn().mockImplementation(() => Promise.resolve(data));
@@ -26,11 +34,9 @@ var editUserJsx = (callbackSpy, empty) => (
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<EditUser
location={empty ? {} : { state: { username: "foo", has_admin: false } }}
deleteUser={callbackSpy}
editUser={callbackSpy}
updateUsers={callbackSpy}
history={{ push: () => {} }}
noChangeEvent={callbackSpy}
/>
</HashRouter>

View File

@@ -1,17 +1,19 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import { Link } from "react-router-dom";
import { Link, useNavigate, useLocation } from "react-router-dom";
import PropTypes from "prop-types";
import GroupSelect from "../GroupSelect/GroupSelect";
import DynamicTable from "../DynamicTable/DynamicTable";
const GroupEdit = (props) => {
var [selected, setSelected] = useState([]),
const [selected, setSelected] = useState([]),
[changed, setChanged] = useState(false),
[errorAlert, setErrorAlert] = useState(null),
navigate = useNavigate(),
location = useLocation(),
limit = useSelector((state) => state.limit);
var dispatch = useDispatch();
const dispatch = useDispatch();
const hasDuplicates = (a) => a.filter((e, i) => a.indexOf(e) != i).length > 0;
const dispatchPageUpdate = (data, page) => {
dispatch({
@@ -23,28 +25,28 @@ const GroupEdit = (props) => {
});
};
var {
const {
addToGroup,
updateProp,
removeFromGroup,
deleteGroup,
updateGroups,
validateUser,
history,
location,
} = props;
console.log("group edit", location, location.state);
useEffect(() => {
if (!location.state) {
history.push("/groups");
return <></>;
navigate("/groups");
}
}, [location]);
var { group_data } = location.state;
var [propobject, setProp] = useState(group_data.properties);
var [propkeys, setPropKeys] = useState([]);
var [propvalues, setPropValues] = useState([]);
const { group_data } = location.state || {};
if (!group_data) return <div></div>;
const [propobject, setProp] = useState(group_data.properties);
const [propkeys, setPropKeys] = useState([]);
const [propvalues, setPropValues] = useState([]);
return (
<div className="container" data-testid="container">
@@ -173,7 +175,7 @@ const GroupEdit = (props) => {
data.status < 300
? updateGroups(0, limit)
.then((data) => dispatchPageUpdate(data, 0))
.then(() => history.push("/groups"))
.then(() => navigate("/groups"))
: setErrorAlert(`Failed to delete group.`);
})
.catch(() => setErrorAlert(`Failed to delete group.`));
@@ -190,15 +192,6 @@ const GroupEdit = (props) => {
};
GroupEdit.propTypes = {
location: PropTypes.shape({
state: PropTypes.shape({
group_data: PropTypes.object,
callback: PropTypes.func,
}),
}),
history: PropTypes.shape({
push: PropTypes.func,
}),
addToGroup: PropTypes.func,
removeFromGroup: PropTypes.func,
deleteGroup: PropTypes.func,

View File

@@ -16,6 +16,14 @@ jest.mock("react-redux", () => ({
useSelector: jest.fn(),
}));
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useLocation: jest.fn().mockImplementation(() => {
return { state: { group_data: { users: ["foo"], name: "group" } } };
}),
useNavigate: jest.fn(),
}));
var mockAsync = (data) =>
jest.fn().mockImplementation(() => Promise.resolve(data));
@@ -28,16 +36,9 @@ var groupEditJsx = (callbackSpy) => (
<Provider store={createStore(() => {}, {})}>
<HashRouter>
<GroupEdit
location={{
state: {
group_data: { users: ["foo"], name: "group" },
callback: () => {},
},
}}
addToGroup={callbackSpy}
removeFromGroup={callbackSpy}
deleteGroup={callbackSpy}
history={{ push: () => callbackSpy }}
updateGroups={callbackSpy}
validateUser={jest.fn().mockImplementation(() => okPacket)}
/>

View File

@@ -2,21 +2,22 @@ import React, { useEffect } from "react";
import { useSelector, useDispatch } from "react-redux";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import { Link, useNavigate } from "react-router-dom";
import { usePaginationParams } from "../../util/paginationParams";
import PaginationFooter from "../PaginationFooter/PaginationFooter";
const Groups = (props) => {
var groups_data = useSelector((state) => state.groups_data),
groups_page = useSelector((state) => state.groups_page),
dispatch = useDispatch();
const groups_data = useSelector((state) => state.groups_data);
const groups_page = useSelector((state) => state.groups_page);
const dispatch = useDispatch();
const navigate = useNavigate();
const { setOffset, offset, setLimit, handleLimit, limit, setPagination } =
const { setOffset, offset, handleLimit, limit, setPagination } =
usePaginationParams();
var total = groups_page ? groups_page.total : undefined;
const total = groups_page ? groups_page.total : undefined;
var { updateGroups, history } = props;
const { updateGroups } = props;
const dispatchPageUpdate = (data, page) => {
setPagination(page);
@@ -55,14 +56,7 @@ const Groups = (props) => {
<span className="badge badge-pill badge-success">
{e.users.length + " users"}
</span>
<Link
to={{
pathname: "/group-edit",
state: {
group_data: e,
},
}}
>
<Link to="/group-edit" state={{ group_data: e }}>
{e.name}
</Link>
</li>
@@ -90,7 +84,7 @@ const Groups = (props) => {
<button
className="btn btn-primary adjacent-span-spacing"
onClick={() => {
history.push("/create-group");
navigate("/create-group");
}}
>
New Group
@@ -106,12 +100,6 @@ const Groups = (props) => {
Groups.propTypes = {
updateUsers: PropTypes.func,
updateGroups: PropTypes.func,
history: PropTypes.shape({
push: PropTypes.func,
}),
location: PropTypes.shape({
search: PropTypes.string,
}),
};
export default Groups;

View File

@@ -27,7 +27,7 @@ var mockAsync = () =>
var groupsJsx = (callbackSpy) => (
<Provider store={createStore(mockReducers, mockAppState())}>
<HashRouter>
<Groups location={{ search: "0" }} updateGroups={callbackSpy} />
<Groups updateGroups={callbackSpy} />
</HashRouter>
</Provider>
);

View File

@@ -15,7 +15,7 @@ import {
} from "react-bootstrap";
import ReactObjectTableViewer from "../ReactObjectTableViewer/ReactObjectTableViewer";
import { Link, useSearchParams } from "react-router-dom";
import { Link, useSearchParams, useNavigate } from "react-router-dom";
import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa";
import "./server-dashboard.css";
@@ -50,6 +50,7 @@ const ServerDashboard = (props) => {
const total = user_page ? user_page.total : undefined;
const dispatch = useDispatch();
const navigate = useNavigate();
var {
updateUsers,
@@ -59,7 +60,6 @@ const ServerDashboard = (props) => {
deleteServer,
startAll,
stopAll,
history,
} = props;
const dispatchPageUpdate = (data, page) => {
@@ -260,8 +260,7 @@ const ServerDashboard = (props) => {
<button
className="btn btn-light btn-xs"
onClick={() =>
history.push({
pathname: "/edit-user",
navigate("/edit-user", {
state: {
username: user.name,
has_admin: user.admin,
@@ -435,7 +434,7 @@ const ServerDashboard = (props) => {
</Col>
<Col md={3}>
{/* div.checkbox required for BS3 CSS */}
<div class="checkbox">
<div className="checkbox">
<label title="check to only show running servers, otherwise show all">
<Form.Check
inline
@@ -605,12 +604,6 @@ ServerDashboard.propTypes = {
startAll: PropTypes.func,
stopAll: PropTypes.func,
dispatch: PropTypes.func,
history: PropTypes.shape({
push: PropTypes.func,
}),
location: PropTypes.shape({
search: PropTypes.string,
}),
};
const SortHandler = (props) => {