admin: move active-servers filter to top

next to name filter, so it's not in the table headings

merges Running & Actions columns,
since it's really just Actions now (server actions & user actions)
This commit is contained in:
Min RK
2024-03-08 09:49:23 +01:00
parent bc3bb47672
commit e540963f20
2 changed files with 60 additions and 64 deletions

View File

@@ -110,14 +110,18 @@ const ServerDashboard = (props) => {
}); });
}; };
const setStateFilter = (state_filter) => { const setStateFilter = (new_state_filter) => {
// persist ?state filter // persist ?state filter
// store in url param, clear when value is default ('') // store in url param, clear when value is default ('')
setSearchParams((params) => { setSearchParams((params) => {
if (!state_filter) { // clear offset when filter changes
if (new_state_filter !== state_filter) {
params.delete("offset");
}
if (!new_state_filter) {
params.delete("state"); params.delete("state");
} else { } else {
params.set("state", state_filter); params.set("state", new_state_filter);
} }
return params; return params;
}); });
@@ -196,7 +200,7 @@ const ServerDashboard = (props) => {
}); });
}; };
const DeleteServerButton = ({ server, user }) => { const DeleteServerButton = ({ server, user }) => {
if (server.name === "") { if (!server.name) {
// It's not possible to delete unnamed servers // It's not possible to delete unnamed servers
return null; return null;
} }
@@ -251,12 +255,10 @@ const ServerDashboard = (props) => {
); );
}; };
const EditUserCell = ({ user }) => { const EditUserButton = ({ user }) => {
return ( return (
<td>
<button <button
className="btn btn-primary btn-xs" className="btn btn-light btn-xs"
style={{ marginRight: 20 }}
onClick={() => onClick={() =>
history.push({ history.push({
pathname: "/edit-user", pathname: "/edit-user",
@@ -269,7 +271,6 @@ const ServerDashboard = (props) => {
> >
Edit User Edit User
</button> </button>
</td>
); );
}; };
@@ -363,8 +364,8 @@ const ServerDashboard = (props) => {
<DeleteServerButton server={server} user={user} /> <DeleteServerButton server={server} user={user} />
<AccessServerButton server={server} /> <AccessServerButton server={server} />
<SpawnPageButton server={server} user={user} /> <SpawnPageButton server={server} user={user} />
<EditUserButton user={user} />
</td> </td>
<EditUserCell user={user} />
</tr>, </tr>,
<tr key={`${userServerName}-detail`}> <tr key={`${userServerName}-detail`}>
<td <td
@@ -432,6 +433,24 @@ const ServerDashboard = (props) => {
onChange={handleSearch} onChange={handleSearch}
/> />
</Col> </Col>
<Col md={3}>
{/* div.checkbox required for BS3 CSS */}
<div class="checkbox">
<label title="check to only show running servers, otherwise show all">
<Form.Check
inline
type="checkbox"
name="active_servers"
id="active-servers-filter"
checked={state_filter == "active"}
onChange={(event) => {
setStateFilter(event.target.checked ? "active" : null);
}}
/>
{"only active servers"}
</label>
</div>
</Col>
<Col md="auto" style={{ float: "right", margin: 15 }}> <Col md="auto" style={{ float: "right", margin: 15 }}>
<Link to="/groups">{"> Manage Groups"}</Link> <Link to="/groups">{"> Manage Groups"}</Link>
@@ -460,23 +479,6 @@ const ServerDashboard = (props) => {
testid="last-activity-sort" testid="last-activity-sort"
/> />
</th> </th>
<th id="running-status-header">
<label title="only show active servers">
<Form.Check
inline
type="checkbox"
name="active_servers"
aria-label="only show active servers"
checked={state_filter == "active"}
onChange={(event) => {
setStateFilter(event.target.checked ? "active" : null);
}}
/>
{state_filter == "active"
? " Active servers"
: " All servers"}
</label>
</th>
<th id="actions-header">Actions</th> <th id="actions-header">Actions</th>
</tr> </tr>
</thead> </thead>
@@ -489,14 +491,13 @@ const ServerDashboard = (props) => {
</Button> </Button>
</Link> </Link>
</td> </td>
<td></td> <td colspan="4" className="admin-header-buttons">
<td></td>
<td>
{/* Start all servers */} {/* Start all servers */}
<Button <Button
variant="primary" variant="primary"
className="start-all" className="start-all"
data-testid="start-all" data-testid="start-all"
title="start all servers on the current page"
onClick={() => { onClick={() => {
Promise.all(startAll(user_data.map((e) => e.name))) Promise.all(startAll(user_data.map((e) => e.name)))
.then((res) => { .then((res) => {
@@ -533,6 +534,7 @@ const ServerDashboard = (props) => {
variant="danger" variant="danger"
className="stop-all" className="stop-all"
data-testid="stop-all" data-testid="stop-all"
title="stop all servers on the current page"
onClick={() => { onClick={() => {
Promise.all(stopAll(user_data.map((e) => e.name))) Promise.all(stopAll(user_data.map((e) => e.name)))
.then((res) => { .then((res) => {
@@ -563,8 +565,8 @@ const ServerDashboard = (props) => {
> >
Stop All Stop All
</Button> </Button>
</td> {/* spacing between start/stop and Shutdown */}
<td> <span style={{ "margin-left": "56px" }}> </span>
{/* Shutdown Jupyterhub */} {/* Shutdown Jupyterhub */}
<Button <Button
variant="danger" variant="danger"
@@ -574,7 +576,6 @@ const ServerDashboard = (props) => {
Shutdown Hub Shutdown Hub
</Button> </Button>
</td> </td>
<td></td>
</tr> </tr>
{servers.flatMap(([user, server]) => serverRow(user, server))} {servers.flatMap(([user, server]) => serverRow(user, server))}
</tbody> </tbody>

View File

@@ -7,6 +7,13 @@
margin-left: auto; margin-left: auto;
} }
.btn-light {
/* backport bs5 btn-light colors */
background-color: #f9fafb;
border-color: #f9fafb;
color: #000;
}
.server-dashboard-container .btn-light { .server-dashboard-container .btn-light {
border: 1px solid #ddd; border: 1px solid #ddd;
} }
@@ -47,11 +54,9 @@ tr.noborder > td {
margin-right: 5px; margin-right: 5px;
} }
.form-check-inline { .admin-header-buttons {
/* inline form check doesn't get inline css /* float header action buttons to the right */
I _think_ this is because our bootstrap css is outdated text-align: right;
*/
display: inline-block;
} }
/* column widths for dashboard /* column widths for dashboard
@@ -66,31 +71,21 @@ goals:
*/ */
.admin-table-head label {
/* clear margin-bottom to keep label on baseline */
margin-bottom: 0px;
}
.admin-table-head #user-header { .admin-table-head #user-header {
} }
.admin-table-head #admin-header { .admin-table-head #admin-header {
width: 64px; width: 64px;
} }
.admin-table-head #server-header {
}
.admin-table-head #last-activity-header { .admin-table-head #last-activity-header {
width: 180px; min-width: 180px;
}
.admin-table-head #running-status-header {
width: 300px;
} }
.admin-table-head #actions-header { .admin-table-head #actions-header {
width: 80px; width: 350px;
} }
/* vertical stack server buttons on small windows */ /* vertical stack server buttons on small windows */
@media (max-width: 991px) { @media (max-width: 991px) {
.admin-table-head #running-status-header { .admin-table-head #actions-header {
width: 140px; width: 140px;
} }
} }