feat: enhance user display name resolution and update related components
This commit is contained in:
56
frontend/src/lib/display-name.test.ts
Normal file
56
frontend/src/lib/display-name.test.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import type { OrganizationMemberRead } from "@/api/generated/model";
|
||||
import {
|
||||
DEFAULT_HUMAN_LABEL,
|
||||
normalizeDisplayName,
|
||||
resolveHumanActorName,
|
||||
resolveMemberDisplayName,
|
||||
} from "./display-name";
|
||||
|
||||
const memberWithUser = (user: {
|
||||
preferred_name?: string | null;
|
||||
name?: string | null;
|
||||
}): OrganizationMemberRead =>
|
||||
({
|
||||
user,
|
||||
}) as OrganizationMemberRead;
|
||||
|
||||
describe("display-name", () => {
|
||||
it("normalizes empty strings to null", () => {
|
||||
expect(normalizeDisplayName(" ")).toBeNull();
|
||||
expect(normalizeDisplayName(" Abhimanyu ")).toBe("Abhimanyu");
|
||||
});
|
||||
|
||||
it("resolves generic labels to fallback names", () => {
|
||||
expect(resolveHumanActorName("Admin", "Abhimanyu")).toBe("Abhimanyu");
|
||||
expect(resolveHumanActorName(" user ", "Abhimanyu")).toBe("Abhimanyu");
|
||||
});
|
||||
|
||||
it("keeps explicit non-generic actor labels", () => {
|
||||
expect(resolveHumanActorName("Abhimanyu", "User")).toBe("Abhimanyu");
|
||||
});
|
||||
|
||||
it("prefers membership preferred_name over name", () => {
|
||||
const member = memberWithUser({
|
||||
preferred_name: "Abhimanyu",
|
||||
name: "Admin",
|
||||
});
|
||||
expect(resolveMemberDisplayName(member)).toBe("Abhimanyu");
|
||||
});
|
||||
|
||||
it("falls back to membership name when preferred_name missing", () => {
|
||||
const member = memberWithUser({
|
||||
preferred_name: null,
|
||||
name: "Abhimanyu",
|
||||
});
|
||||
expect(resolveMemberDisplayName(member)).toBe("Abhimanyu");
|
||||
});
|
||||
|
||||
it("returns default user label when member names are unavailable", () => {
|
||||
expect(resolveMemberDisplayName(null)).toBe(DEFAULT_HUMAN_LABEL);
|
||||
expect(resolveMemberDisplayName(memberWithUser({ name: "Admin" }))).toBe(
|
||||
DEFAULT_HUMAN_LABEL,
|
||||
);
|
||||
});
|
||||
});
|
||||
33
frontend/src/lib/display-name.ts
Normal file
33
frontend/src/lib/display-name.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import type { OrganizationMemberRead } from "@/api/generated/model";
|
||||
|
||||
export const DEFAULT_HUMAN_LABEL = "User";
|
||||
|
||||
export const normalizeDisplayName = (
|
||||
value: string | null | undefined,
|
||||
): string | null => {
|
||||
const trimmed = (value ?? "").trim();
|
||||
return trimmed.length > 0 ? trimmed : null;
|
||||
};
|
||||
|
||||
export const resolveHumanActorName = (
|
||||
value: string | null | undefined,
|
||||
fallbackName: string = DEFAULT_HUMAN_LABEL,
|
||||
): string => {
|
||||
const normalized = normalizeDisplayName(value);
|
||||
if (!normalized) return fallbackName;
|
||||
const lowered = normalized.toLowerCase();
|
||||
if (lowered === "admin" || lowered === "user") {
|
||||
return fallbackName;
|
||||
}
|
||||
return normalized;
|
||||
};
|
||||
|
||||
export const resolveMemberDisplayName = (
|
||||
member: OrganizationMemberRead | null | undefined,
|
||||
fallbackName: string = DEFAULT_HUMAN_LABEL,
|
||||
): string =>
|
||||
resolveHumanActorName(
|
||||
normalizeDisplayName(member?.user?.preferred_name) ??
|
||||
normalizeDisplayName(member?.user?.name),
|
||||
fallbackName,
|
||||
);
|
||||
Reference in New Issue
Block a user