all the haul

This commit is contained in:
2026-04-07 23:56:31 +00:00
parent 87cce83030
commit 24f303355b
244 changed files with 33743 additions and 11249 deletions
+16 -7
View File
@@ -37,13 +37,13 @@ export const load: PageServerLoad = async ({ locals }) => {
try {
const rolesResult = await optima.users.fetchRoles(
accessToken,
user.id,
user.id
);
return { ...user, roleDetails: rolesResult?.data ?? [] };
} catch {
return { ...user, roleDetails: [] };
}
}),
})
);
return {
@@ -66,21 +66,30 @@ export const actions: Actions = {
const formData = await request.formData();
const id = (formData.get("id") as string)?.trim();
const name = (formData.get("name") as string)?.trim();
const firstName = (formData.get("firstName") as string)?.trim();
const lastName = (formData.get("lastName") as string)?.trim();
const image = (formData.get("image") as string)?.trim() || undefined;
const rolesJson = (formData.get("roles") as string)?.trim();
const permissionsJson = (formData.get("permissions") as string)?.trim();
if (!id || !name) {
return fail(400, { message: "User ID and name are required." });
if (!id) {
return fail(400, { message: "User ID is required." });
}
const updates: {
name: string;
firstName?: string | null;
lastName?: string | null;
image?: string;
roles?: string[];
permissions?: string[];
} = { name, image };
} = { image };
if (formData.has("firstName")) {
updates.firstName = firstName || null;
}
if (formData.has("lastName")) {
updates.lastName = lastName || null;
}
if (rolesJson) {
try {
+12 -6
View File
@@ -29,13 +29,18 @@
$: users = data.users;
$: allRoles = data.roles;
function fullName(user: UserWithRoles): string {
const computed = `${user.firstName ?? ""} ${user.lastName ?? ""}`.trim();
return computed || user.name || user.login || user.email;
}
// Search / filter
let searchQuery = "";
$: filteredUsers = users.filter((u) => {
if (!searchQuery.trim()) return true;
const q = searchQuery.toLowerCase();
return (
u.name.toLowerCase().includes(q) ||
fullName(u).toLowerCase().includes(q) ||
u.email.toLowerCase().includes(q) ||
u.login.toLowerCase().includes(q)
);
@@ -151,8 +156,9 @@
onCancel={cancelDelete}
handleEnhance={handleDeleteEnhance}
>
Are you sure you want to delete <strong>{userToDelete?.name}</strong>? This
action cannot be undone.
Are you sure you want to delete <strong
>{userToDelete ? fullName(userToDelete) : "this user"}</strong
>? This action cannot be undone.
</DeleteConfirmDialog>
<div class="admin-table-header">
@@ -211,15 +217,15 @@
{#if user.image}
<img
src={user.image}
alt={user.name}
alt={fullName(user)}
class="user-table-avatar"
/>
{:else}
<div class="user-table-avatar user-table-avatar-initials">
{initials(user.name)}
{initials(fullName(user))}
</div>
{/if}
<span class="user-table-name">{user.name}</span>
<span class="user-table-name">{fullName(user)}</span>
</div>
</td>
<td>
+23 -12
View File
@@ -20,6 +20,10 @@ const { mockOptima, mockCheckPermissions, mockHandleApiError, mockFail } =
})),
}));
vi.mock("$env/static/public", () => ({
PUBLIC_API_URL: "https://api.example.com",
}));
vi.mock("$lib", () => ({ optima: mockOptima }));
vi.mock("$lib/permissions", () => ({
checkPermissions: mockCheckPermissions,
@@ -102,15 +106,15 @@ describe("admin/users +page.server.ts", () => {
});
});
it("returns 400 when required fields are missing", async () => {
it("returns 400 when user ID is missing", async () => {
await actions.updateUser({
locals: { session: { accessToken: "tok" } },
request: {
formData: vi.fn().mockResolvedValue(createFormData({ id: "u1" })),
formData: vi.fn().mockResolvedValue(createFormData({})),
},
} as any);
expect(mockFail).toHaveBeenCalledWith(400, {
message: "User ID and name are required.",
message: "User ID is required.",
});
});
@@ -120,14 +124,19 @@ describe("admin/users +page.server.ts", () => {
const result = await actions.updateUser({
locals: { session: { accessToken: "tok" } },
request: {
formData: vi
.fn()
.mockResolvedValue(createFormData({ id: "u1", name: "Updated" })),
formData: vi.fn().mockResolvedValue(
createFormData({
id: "u1",
firstName: "Updated",
lastName: "User",
})
),
},
} as any);
expect(mockOptima.users.update).toHaveBeenCalledWith("tok", "u1", {
name: "Updated",
firstName: "Updated",
lastName: "User",
image: undefined,
});
expect(result).toEqual({});
@@ -142,15 +151,17 @@ describe("admin/users +page.server.ts", () => {
formData: vi.fn().mockResolvedValue(
createFormData({
id: "u1",
name: "Updated",
firstName: "Updated",
lastName: "User",
roles: '["r1","r2"]',
}),
})
),
},
} as any);
expect(mockOptima.users.update).toHaveBeenCalledWith("tok", "u1", {
name: "Updated",
firstName: "Updated",
lastName: "User",
image: undefined,
roles: ["r1", "r2"],
});
@@ -163,9 +174,9 @@ describe("admin/users +page.server.ts", () => {
formData: vi.fn().mockResolvedValue(
createFormData({
id: "u1",
name: "Updated",
firstName: "Updated",
roles: "bad json",
}),
})
),
},
} as any);