fix(FN-3808): increase create-room member role typography
- Increase the member role text sizing in CreateRoomModal for better readability - Update CreateRoomModal.css with the adjusted typography value - Keep the change scoped to create-room role styling only Fusion-Task-Id: FN-3808
This commit is contained in:
94
packages/dashboard/app/api/__tests__/chat-rooms-api.test.ts
Normal file
94
packages/dashboard/app/api/__tests__/chat-rooms-api.test.ts
Normal file
@@ -0,0 +1,94 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
addChatRoomMember,
|
||||
createChatRoom,
|
||||
deleteChatRoom,
|
||||
deleteChatRoomMessage,
|
||||
fetchChatRoom,
|
||||
fetchChatRoomMembers,
|
||||
fetchChatRoomMessages,
|
||||
fetchChatRooms,
|
||||
postChatRoomMessage,
|
||||
removeChatRoomMember,
|
||||
updateChatRoom,
|
||||
} from "../legacy";
|
||||
|
||||
function jsonResponse(payload: unknown): Response {
|
||||
return new Response(JSON.stringify(payload), { status: 200, headers: { "content-type": "application/json" } });
|
||||
}
|
||||
|
||||
describe("chat room legacy API client", () => {
|
||||
afterEach(() => {
|
||||
vi.restoreAllMocks();
|
||||
});
|
||||
|
||||
it("builds request for fetchChatRooms", async () => {
|
||||
const fetchMock = vi.spyOn(globalThis, "fetch").mockImplementation(async () => jsonResponse({ rooms: [] }));
|
||||
await fetchChatRooms({ status: "active", agentId: "agent-1" }, "proj-1");
|
||||
|
||||
const [url, init] = fetchMock.mock.calls[0] as [string, RequestInit];
|
||||
expect(url).toContain("/api/chat/rooms?");
|
||||
expect(url).toContain("projectId=proj-1");
|
||||
expect(url).toContain("status=active");
|
||||
expect(url).toContain("agentId=agent-1");
|
||||
expect(init.method).toBeUndefined();
|
||||
});
|
||||
|
||||
it("builds CRUD room endpoints", async () => {
|
||||
const fetchMock = vi.spyOn(globalThis, "fetch").mockImplementation(async () => jsonResponse({ success: true }));
|
||||
|
||||
await fetchChatRoom("room-1", "proj-1");
|
||||
await createChatRoom({ name: "Engineering" }, "proj-1");
|
||||
await updateChatRoom("room-1", { description: "desc" }, "proj-1");
|
||||
await deleteChatRoom("room-1", "proj-1");
|
||||
|
||||
expect((fetchMock.mock.calls[0] as [string])[0]).toContain("/api/chat/rooms/room-1?projectId=proj-1");
|
||||
|
||||
const [, createInit] = fetchMock.mock.calls[1] as [string, RequestInit];
|
||||
expect(createInit.method).toBe("POST");
|
||||
expect(createInit.body).toBe(JSON.stringify({ name: "Engineering", projectId: "proj-1" }));
|
||||
|
||||
const [, updateInit] = fetchMock.mock.calls[2] as [string, RequestInit];
|
||||
expect(updateInit.method).toBe("PATCH");
|
||||
expect(updateInit.body).toBe(JSON.stringify({ description: "desc" }));
|
||||
|
||||
const [, deleteInit] = fetchMock.mock.calls[3] as [string, RequestInit];
|
||||
expect(deleteInit.method).toBe("DELETE");
|
||||
});
|
||||
|
||||
it("builds member endpoints", async () => {
|
||||
const fetchMock = vi.spyOn(globalThis, "fetch").mockImplementation(async () => jsonResponse({ success: true }));
|
||||
|
||||
await fetchChatRoomMembers("room-1", "proj-2");
|
||||
await addChatRoomMember("room-1", { agentId: "agent-2", role: "owner" }, "proj-2");
|
||||
await removeChatRoomMember("room-1", "agent-2", "proj-2");
|
||||
|
||||
expect((fetchMock.mock.calls[0] as [string])[0]).toContain("/api/chat/rooms/room-1/members?projectId=proj-2");
|
||||
const [, addInit] = fetchMock.mock.calls[1] as [string, RequestInit];
|
||||
expect(addInit.method).toBe("POST");
|
||||
expect(addInit.body).toBe(JSON.stringify({ agentId: "agent-2", role: "owner" }));
|
||||
expect((fetchMock.mock.calls[2] as [string])[0]).toContain("/api/chat/rooms/room-1/members/agent-2?projectId=proj-2");
|
||||
});
|
||||
|
||||
it("builds message endpoints", async () => {
|
||||
const fetchMock = vi.spyOn(globalThis, "fetch").mockImplementation(async () => jsonResponse({ success: true }));
|
||||
|
||||
await fetchChatRoomMessages("room-1", { limit: 2, offset: 1, before: "2026-01-01" }, "proj-3");
|
||||
await postChatRoomMessage("room-1", { content: "hello", mentions: ["agent-x"] }, "proj-3");
|
||||
await deleteChatRoomMessage("room-1", "msg-1", "proj-3");
|
||||
|
||||
const [listUrl] = fetchMock.mock.calls[0] as [string, RequestInit];
|
||||
expect(listUrl).toContain("/api/chat/rooms/room-1/messages?");
|
||||
expect(listUrl).toContain("projectId=proj-3");
|
||||
expect(listUrl).toContain("limit=2");
|
||||
expect(listUrl).toContain("offset=1");
|
||||
expect(listUrl).toContain("before=2026-01-01");
|
||||
|
||||
const [, postInit] = fetchMock.mock.calls[1] as [string, RequestInit];
|
||||
expect(postInit.method).toBe("POST");
|
||||
expect(postInit.body).toBe(JSON.stringify({ content: "hello", mentions: ["agent-x"] }));
|
||||
|
||||
const [, delInit] = fetchMock.mock.calls[2] as [string, RequestInit];
|
||||
expect(delInit.method).toBe("DELETE");
|
||||
});
|
||||
});
|
||||
@@ -42,7 +42,11 @@ import type {
|
||||
AgentRating,
|
||||
AgentRatingSummary,
|
||||
AgentRatingInput,
|
||||
ChatAttachment,
|
||||
ChatMessage,
|
||||
ChatRoom,
|
||||
ChatRoomMember,
|
||||
ChatRoomMessage,
|
||||
EnrichedChatSession,
|
||||
TodoList,
|
||||
TodoItem,
|
||||
@@ -8052,6 +8056,27 @@ export interface ChatMessageListResponse {
|
||||
messages: ChatMessage[];
|
||||
}
|
||||
|
||||
export interface ChatRoomListResponse {
|
||||
rooms: ChatRoom[];
|
||||
}
|
||||
|
||||
export interface ChatRoomResponse {
|
||||
room: ChatRoom;
|
||||
members?: ChatRoomMember[];
|
||||
}
|
||||
|
||||
export interface ChatRoomMembersResponse {
|
||||
members: ChatRoomMember[];
|
||||
}
|
||||
|
||||
export interface ChatRoomMessageListResponse {
|
||||
messages: ChatRoomMessage[];
|
||||
}
|
||||
|
||||
export interface ChatRoomMessageResponse {
|
||||
message: ChatRoomMessage;
|
||||
}
|
||||
|
||||
/** Fetch all chat sessions for a project */
|
||||
export function fetchChatSessions(projectId?: string, status?: string): Promise<ChatSessionListResponse> {
|
||||
const search = new URLSearchParams();
|
||||
@@ -8165,6 +8190,114 @@ export function deleteChatMessage(
|
||||
);
|
||||
}
|
||||
|
||||
export function fetchChatRooms(
|
||||
options: { status?: string; agentId?: string } = {},
|
||||
projectId?: string,
|
||||
): Promise<ChatRoomListResponse> {
|
||||
const search = new URLSearchParams();
|
||||
if (projectId) search.set("projectId", projectId);
|
||||
if (options.status) search.set("status", options.status);
|
||||
if (options.agentId) search.set("agentId", options.agentId);
|
||||
const qs = search.toString();
|
||||
return api<ChatRoomListResponse>(`/chat/rooms${qs ? `?${qs}` : ""}`);
|
||||
}
|
||||
|
||||
export function fetchChatRoom(id: string, projectId?: string): Promise<ChatRoomResponse> {
|
||||
return api<ChatRoomResponse>(withProjectId(`/chat/rooms/${encodeURIComponent(id)}`, projectId));
|
||||
}
|
||||
|
||||
export function createChatRoom(
|
||||
input: { name: string; description?: string | null; createdBy?: string | null; memberAgentIds?: string[] },
|
||||
projectId?: string,
|
||||
): Promise<ChatRoomResponse> {
|
||||
const body = { ...input, ...(projectId ? { projectId } : {}) };
|
||||
return api<ChatRoomResponse>(withProjectId("/chat/rooms", projectId), {
|
||||
method: "POST",
|
||||
body: JSON.stringify(body),
|
||||
});
|
||||
}
|
||||
|
||||
export function updateChatRoom(
|
||||
id: string,
|
||||
updates: { name?: string; description?: string | null; status?: "active" | "archived" },
|
||||
projectId?: string,
|
||||
): Promise<{ room: ChatRoom }> {
|
||||
return api<{ room: ChatRoom }>(withProjectId(`/chat/rooms/${encodeURIComponent(id)}`, projectId), {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify(updates),
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteChatRoom(id: string, projectId?: string): Promise<{ success: boolean }> {
|
||||
return api<{ success: boolean }>(withProjectId(`/chat/rooms/${encodeURIComponent(id)}`, projectId), {
|
||||
method: "DELETE",
|
||||
});
|
||||
}
|
||||
|
||||
export function fetchChatRoomMembers(id: string, projectId?: string): Promise<ChatRoomMembersResponse> {
|
||||
return api<ChatRoomMembersResponse>(withProjectId(`/chat/rooms/${encodeURIComponent(id)}/members`, projectId));
|
||||
}
|
||||
|
||||
export function addChatRoomMember(
|
||||
id: string,
|
||||
input: { agentId: string; role?: "owner" | "member" },
|
||||
projectId?: string,
|
||||
): Promise<{ member: ChatRoomMember }> {
|
||||
return api<{ member: ChatRoomMember }>(withProjectId(`/chat/rooms/${encodeURIComponent(id)}/members`, projectId), {
|
||||
method: "POST",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export function removeChatRoomMember(id: string, agentId: string, projectId?: string): Promise<{ success: boolean }> {
|
||||
return api<{ success: boolean }>(
|
||||
withProjectId(`/chat/rooms/${encodeURIComponent(id)}/members/${encodeURIComponent(agentId)}`, projectId),
|
||||
{ method: "DELETE" },
|
||||
);
|
||||
}
|
||||
|
||||
export function fetchChatRoomMessages(
|
||||
id: string,
|
||||
opts?: { limit?: number; offset?: number; before?: string },
|
||||
projectId?: string,
|
||||
): Promise<ChatRoomMessageListResponse> {
|
||||
const search = new URLSearchParams();
|
||||
if (opts?.limit !== undefined) search.set("limit", String(opts.limit));
|
||||
if (opts?.offset !== undefined) search.set("offset", String(opts.offset));
|
||||
if (opts?.before) search.set("before", opts.before);
|
||||
const qs = search.toString();
|
||||
return api<ChatRoomMessageListResponse>(
|
||||
withProjectId(`/chat/rooms/${encodeURIComponent(id)}/messages${qs ? `?${qs}` : ""}`, projectId),
|
||||
);
|
||||
}
|
||||
|
||||
export function postChatRoomMessage(
|
||||
id: string,
|
||||
input: { content: string; senderAgentId?: null; mentions?: string[]; attachments?: File[] | ChatAttachment[] },
|
||||
projectId?: string,
|
||||
): Promise<ChatRoomMessageResponse> {
|
||||
return api<ChatRoomMessageResponse>(withProjectId(`/chat/rooms/${encodeURIComponent(id)}/messages`, projectId), {
|
||||
method: "POST",
|
||||
body: JSON.stringify(input),
|
||||
});
|
||||
}
|
||||
|
||||
export function deleteChatRoomMessage(
|
||||
id: string,
|
||||
messageId: string,
|
||||
projectId?: string,
|
||||
): Promise<{ success: boolean }> {
|
||||
return api<{ success: boolean }>(
|
||||
withProjectId(`/chat/rooms/${encodeURIComponent(id)}/messages/${encodeURIComponent(messageId)}`, projectId),
|
||||
{ method: "DELETE" },
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Room POST /messages in FN-3808 is persist-only (201 JSON response).
|
||||
* Do not add streamChatRoomResponse until FN-3810 introduces AI invocation/streaming.
|
||||
*/
|
||||
|
||||
/** Cancel an in-flight chat generation. */
|
||||
export function cancelChatResponse(
|
||||
sessionId: string,
|
||||
|
||||
Reference in New Issue
Block a user