mirror of
https://github.com/jupyterhub/jupyterhub.git
synced 2025-10-12 12:33:02 +00:00
Add search bar for user name
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
"eslint-plugin-unused-imports": "^1.1.1",
|
||||
"file-loader": "^6.2.0",
|
||||
"history": "^5.0.0",
|
||||
"lodash.debounce": "^4.0.8",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^17.0.1",
|
||||
"react-bootstrap": "^1.4.0",
|
||||
@@ -51,6 +52,7 @@
|
||||
"react-router-dom": "^5.2.0",
|
||||
"recompose": "^0.30.0",
|
||||
"redux": "^4.0.5",
|
||||
"regenerator-runtime": "^0.13.9",
|
||||
"style-loader": "^2.0.0",
|
||||
"webpack": "^5.6.0",
|
||||
"webpack-cli": "^3.3.4",
|
||||
|
@@ -1,8 +1,9 @@
|
||||
import React, { useState } from "react";
|
||||
import regeneratorRuntime from "regenerator-runtime";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import { Button } from "react-bootstrap";
|
||||
import { Button, Col, Row, FormControl } from "react-bootstrap";
|
||||
import { Link } from "react-router-dom";
|
||||
import { FaSort, FaSortUp, FaSortDown } from "react-icons/fa";
|
||||
|
||||
@@ -37,6 +38,7 @@ const ServerDashboard = (props) => {
|
||||
|
||||
var [errorAlert, setErrorAlert] = useState(null);
|
||||
var [sortMethod, setSortMethod] = useState(null);
|
||||
var [name_filter, setNameFilter] = useState("");
|
||||
var [disabledButtons, setDisabledButtons] = useState({});
|
||||
|
||||
var user_data = useSelector((state) => state.user_data),
|
||||
@@ -45,7 +47,7 @@ const ServerDashboard = (props) => {
|
||||
page = parseInt(new URLSearchParams(props.location.search).get("page"));
|
||||
|
||||
page = isNaN(page) ? 0 : page;
|
||||
var slice = [page * limit, limit];
|
||||
var slice = [page * limit, limit, name_filter];
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
@@ -77,6 +79,14 @@ const ServerDashboard = (props) => {
|
||||
updateUsers(...slice).then((data) => dispatchPageUpdate(data, page));
|
||||
}
|
||||
|
||||
var debounce = require("lodash.debounce");
|
||||
const handleSearch = debounce(async (event) => {
|
||||
setNameFilter(event.target.value);
|
||||
updateUsers(page * limit, limit, event.target.value).then((data) =>
|
||||
dispatchPageUpdate(data, page)
|
||||
);
|
||||
}, 300);
|
||||
|
||||
if (sortMethod != null) {
|
||||
user_data = sortMethod(user_data);
|
||||
}
|
||||
@@ -203,10 +213,22 @@ const ServerDashboard = (props) => {
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
<div className="manage-groups" style={{ float: "right", margin: "20px" }}>
|
||||
<Link to="/groups">{"> Manage Groups"}</Link>
|
||||
</div>
|
||||
<div className="server-dashboard-container">
|
||||
<Row>
|
||||
<Col md={4}>
|
||||
<FormControl
|
||||
type="text"
|
||||
name="user_search"
|
||||
placeholder="Search users"
|
||||
defaultValue={name_filter}
|
||||
onChange={handleSearch}
|
||||
/>
|
||||
</Col>
|
||||
|
||||
<Col md="auto" style={{ float: "right", margin: 15 }}>
|
||||
<Link to="/groups">{"> Manage Groups"}</Link>
|
||||
</Col>
|
||||
</Row>
|
||||
<table className="table table-striped table-bordered table-hover">
|
||||
<thead className="admin-table-head">
|
||||
<tr>
|
||||
|
@@ -2,10 +2,11 @@ import { withProps } from "recompose";
|
||||
import { jhapiRequest } from "./jhapiUtil";
|
||||
|
||||
const withAPI = withProps(() => ({
|
||||
updateUsers: (offset, limit) =>
|
||||
jhapiRequest(`/users?offset=${offset}&limit=${limit}`, "GET").then((data) =>
|
||||
data.json()
|
||||
),
|
||||
updateUsers: (offset, limit, name_filter) =>
|
||||
jhapiRequest(
|
||||
`/users?offset=${offset}&limit=${limit}&name_filter=${name_filter}`,
|
||||
"GET"
|
||||
).then((data) => data.json()),
|
||||
updateGroups: (offset, limit) =>
|
||||
jhapiRequest(`/groups?offset=${offset}&limit=${limit}`, "GET").then(
|
||||
(data) => data.json()
|
||||
|
2240
jsx/yarn.lock
2240
jsx/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -84,6 +84,7 @@ class UserListAPIHandler(APIHandler):
|
||||
@needs_scope('list:users')
|
||||
def get(self):
|
||||
state_filter = self.get_argument("state", None)
|
||||
name_filter = self.get_argument("name_filter", None)
|
||||
offset, limit = self.get_api_pagination()
|
||||
|
||||
# post_filter
|
||||
@@ -148,6 +149,9 @@ class UserListAPIHandler(APIHandler):
|
||||
else:
|
||||
query = query.filter(or_(*filters))
|
||||
|
||||
if name_filter:
|
||||
query = query.filter(orm.User.name.ilike(f'%{name_filter}%'))
|
||||
|
||||
full_query = query
|
||||
query = query.order_by(orm.User.id.asc()).offset(offset).limit(limit)
|
||||
|
||||
|
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user