-
- {shown.slice(0, 2)}
-
+
{t("edit.title", { name: user.displayName || user.username })}
diff --git a/client/src/components/users/__tests__/AccountPoolCard.test.tsx b/client/src/components/users/__tests__/AccountPoolCard.test.tsx
index f658f106..8b95cf3f 100644
--- a/client/src/components/users/__tests__/AccountPoolCard.test.tsx
+++ b/client/src/components/users/__tests__/AccountPoolCard.test.tsx
@@ -33,7 +33,7 @@ const accountPool = vi.hoisted(() => ({
updateGroup: vi.fn(),
deleteGroup: vi.fn(),
}));
-const users = vi.hoisted(() => ({ list: vi.fn() }));
+const users = vi.hoisted(() => ({ list: vi.fn(), avatarUrl: () => null }));
const aiTools = vi.hoisted(() => ({
list: vi.fn(),
ompSharing: vi.fn(),
diff --git a/client/src/components/users/__tests__/UserEditDialog.test.tsx b/client/src/components/users/__tests__/UserEditDialog.test.tsx
index 3cdf23b7..d82cda1f 100644
--- a/client/src/components/users/__tests__/UserEditDialog.test.tsx
+++ b/client/src/components/users/__tests__/UserEditDialog.test.tsx
@@ -13,7 +13,12 @@ import { render, screen, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import type { ServerUserUsage } from "../../../lib/api";
-const users = vi.hoisted(() => ({ get: vi.fn(), update: vi.fn(), remove: vi.fn() }));
+const users = vi.hoisted(() => ({
+ get: vi.fn(),
+ update: vi.fn(),
+ remove: vi.fn(),
+ avatarUrl: () => null,
+}));
const confirmDialog = vi.hoisted(() => vi.fn());
vi.mock("../../../lib/confirm", () => ({ confirmDialog }));
const lanes = vi.hoisted(() => ({ list: vi.fn() }));
diff --git a/client/src/components/users/__tests__/UserQuota.test.tsx b/client/src/components/users/__tests__/UserQuota.test.tsx
index 5c05af43..4d6d50a1 100644
--- a/client/src/components/users/__tests__/UserQuota.test.tsx
+++ b/client/src/components/users/__tests__/UserQuota.test.tsx
@@ -16,6 +16,7 @@ const users = vi.hoisted(() => ({
setQuotaDefault: vi.fn(),
update: vi.fn(),
get: vi.fn(),
+ avatarUrl: () => null,
}));
const lanes = vi.hoisted(() => ({ list: vi.fn() }));
vi.mock("../../../lib/api", async (importOriginal) => {
diff --git a/client/src/lib/api.ts b/client/src/lib/api.ts
index 7a0a79b1..b99771e4 100644
--- a/client/src/lib/api.ts
+++ b/client/src/lib/api.ts
@@ -684,6 +684,8 @@ export interface HostUsageGroup {
username?: string;
/** The user's display name, null when none is set (absent from an older server). */
displayName?: string | null;
+ /** When the user's avatar was last set (null = none; absent from an older server). */
+ avatarAt?: string | null;
/** % of the whole machine's CPU (100 = every core busy) over the sample. */
cpu: number;
/** Resident memory, bytes (shared pages count in every process). */
diff --git a/server/lib/host-stats.js b/server/lib/host-stats.js
index b2180bcf..84f13b20 100644
--- a/server/lib/host-stats.js
+++ b/server/lib/host-stats.js
@@ -555,12 +555,13 @@ async function usage(t0, t1, p0, p1, mem) {
const round = (n) => Math.round(n * 10) / 10;
-/** A user's group fields: id, username and display name (every viewer reads them). */
+/** A user's group fields: id, username, display name and avatar version (every viewer reads them). */
const userExtra = (u) => ({
kind: "user",
userId: u.id,
username: u.username,
displayName: u.displayName ?? null,
+ avatarAt: u.avatarAt ?? null,
});
async function collect() {