mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-14 13:33:00 +00:00
update navigation for react-router v6
This commit is contained in:
@@ -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;
|
||||
|
@@ -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>
|
||||
);
|
||||
|
@@ -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;
|
||||
|
@@ -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>
|
||||
);
|
||||
|
@@ -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,
|
||||
|
@@ -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>
|
||||
|
@@ -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,
|
||||
|
@@ -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)}
|
||||
/>
|
||||
|
@@ -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;
|
||||
|
@@ -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>
|
||||
);
|
||||
|
@@ -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) => {
|
||||
|
Reference in New Issue
Block a user