From 58f26dda7bb37ba2161f672803459bf77249d90b Mon Sep 17 00:00:00 2001 From: DualFroz Date: Fri, 11 Sep 2026 22:53:07 +0200 Subject: [PATCH] admin: show the user last_activity the table is sorted by The 'Last Activity' column rendered the spawner's last_activity while the sort handler asks the API for ?sort=last_activity, which orders users by User.last_activity. The two fields differ, so clicking the sort arrows reordered rows in a way the column did not explain. Render User.last_activity in the column; the per-server value is still shown in the collapsed Server details. --- .../ServerDashboard/ServerDashboard.jsx | 4 +- .../ServerDashboard/ServerDashboard.test.js | 60 +++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/jsx/src/components/ServerDashboard/ServerDashboard.jsx b/jsx/src/components/ServerDashboard/ServerDashboard.jsx index a0a9421..935a2b7 100644 --- a/jsx/src/components/ServerDashboard/ServerDashboard.jsx +++ b/jsx/src/components/ServerDashboard/ServerDashboard.jsx @@ -428,7 +428,9 @@ const ServerDashboard = (props) => {

{server.name}

- {server.last_activity ? timeSince(server.last_activity) : "Never"} + {/* sorted server-side on the user's last_activity; the per-server + value is in the collapsed Server details below */} + {user.last_activity ? timeSince(user.last_activity) : "Never"} {server.started ? timeSince(server.started) : "Never"} diff --git a/jsx/src/components/ServerDashboard/ServerDashboard.test.js b/jsx/src/components/ServerDashboard/ServerDashboard.test.js index 02355f9..dd1fb48 100644 --- a/jsx/src/components/ServerDashboard/ServerDashboard.test.js +++ b/jsx/src/components/ServerDashboard/ServerDashboard.test.js @@ -16,6 +16,7 @@ import regeneratorRuntime from "regenerator-runtime"; import ServerDashboard from "./ServerDashboard"; import { initialState, reducers } from "../../Store"; +import { timeSince } from "../../util/timeSince"; jest.mock("react-redux", () => ({ ...jest.requireActual("react-redux"), @@ -818,6 +819,65 @@ test("Shows 'Never' for server start time when server never started", async () = expect(startTimeCell.textContent).toBe("Never"); }); +test("Shows the user last activity that the table is sorted by", async () => { + // the column is sorted server-side on User.last_activity, so it has to show + // that field and not the spawner's + const userActivity = new Date(Date.now() - 5 * 60 * 1000).toISOString(); + const serverActivity = new Date( + Date.now() - 3 * 60 * 60 * 1000, + ).toISOString(); + const user = { + ...newUser("testuser"), + server: null, + last_activity: userActivity, + servers: { + "": { + name: "", + last_activity: serverActivity, + started: serverActivity, + ready: true, + url: "/user/testuser/", + }, + }, + }; + + useSelector.mockImplementation((callback) => { + return callback({ + user_data: [user], + user_page: { offset: 0, limit: 2, total: 1 }, + limit: 2, + }); + }); + + await act(async () => { + render(serverDashboardJsx()); + }); + + expect(screen.getByTestId("user-row-last-activity").textContent).toBe( + timeSince(userActivity), + ); +}); + +test("Shows 'Never' for last activity when the user was never active", async () => { + const user = { ...newUser("testuser"), server: null, last_activity: null }; + + useSelector.mockImplementation((callback) => { + return callback({ + user_data: [user], + user_page: { offset: 0, limit: 2, total: 1 }, + limit: 2, + }); + }); + + await act(async () => { + render(serverDashboardJsx()); + }); + + expect(screen.getByTestId("user-row-last-activity").textContent).toBe( + "Never", + ); +}); + test("Displays profile information correctly", async () => { await act(async () => { render(serverDashboardJsx());