Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions components/Icon/resolver.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,9 @@ export const Icons = {
clock: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-clock-icon lucide-clock"><path d="M12 6v6l4 2"/><circle cx="12" cy="12" r="10"/></svg>
),
disc: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-disc3-icon lucide-disc-3"><circle cx="12" cy="12" r="10"/><path d="M6 12c0-1.7.7-3.2 1.8-4.2"/><circle cx="12" cy="12" r="2"/><path d="M18 12c0 1.7-.7 3.2-1.8 4.2"/></svg>
),
files: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-folders-icon lucide-folders"><path d="M5 8h14a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2z"/><path d="M7 8V6a2 2 0 0 1 2-2h2l2 2h6"/></svg>
),
Expand Down
6 changes: 6 additions & 0 deletions components/SideMenu/SideMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import AgentsNavItem from "../Sidebar/AgentsNavItem";
import { usePathname } from "next/navigation";
import TasksNavItem from "../Sidebar/TasksNavItem";
import FilesNavItem from "../Sidebar/FilesNavItem";
import CatalogsNavItem from "../Sidebar/CatalogsNavItem";

const SideMenu = ({
isVisible,
Expand All @@ -33,6 +34,7 @@ const SideMenu = ({
const isAgents = pathname.includes("/agents");
const isTasks = pathname.includes("/tasks");
const isFiles = pathname.includes("/files");
const isCatalogs = pathname.includes("/catalogs");

const goToItem = (link?: string) => {
if (isPrepared()) {
Expand Down Expand Up @@ -88,6 +90,10 @@ const SideMenu = ({
</Button>
)}
<div className="flex flex-col gap-1 pt-2">
<CatalogsNavItem
isActive={isCatalogs}
onClick={() => goToItem("catalogs")}
/>
<AgentsNavItem
isActive={isAgents}
onClick={() => goToItem("agents")}
Expand Down
26 changes: 26 additions & 0 deletions components/Sidebar/CatalogsNavItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import NavButton from "./NavButton";

export interface CatalogsNavItemProps {
isActive: boolean;
isExpanded?: boolean;
onClick: () => void;
}

const CatalogsNavItem = ({
isActive,
isExpanded,
onClick,
}: CatalogsNavItemProps) => {
return (
<NavButton
icon="disc"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: Flag AI Slop and Fabricated Changes

The PR description explicitly states CatalogsNavItem uses a book icon, but the implementation uses icon="disc". This is a clear mismatch between the documented behavior and the actual code. Please align the icon choice with the PR description, or update the description to reflect the chosen disc icon.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At components/Sidebar/CatalogsNavItem.tsx, line 16:

<comment>The PR description explicitly states CatalogsNavItem uses a `book` icon, but the implementation uses `icon="disc"`. This is a clear mismatch between the documented behavior and the actual code. Please align the icon choice with the PR description, or update the description to reflect the chosen `disc` icon.</comment>

<file context>
@@ -13,7 +13,7 @@ const CatalogsNavItem = ({
   return (
     <NavButton
-      icon="book"
+      icon="disc"
       label="Catalogs"
       isActive={isActive}
</file context>

label="Catalogs"
isActive={isActive}
isExpanded={isExpanded}
onClick={onClick}
aria-label="View catalogs"
/>
);
};

export default CatalogsNavItem;
2 changes: 2 additions & 0 deletions components/Sidebar/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const Menu = ({ isExpanded, isPinned = false, onTogglePin }: MenuProps) => {
const isAgents = pathname.includes("/agents");
const isTasks = pathname.includes("/tasks");
const isFiles = pathname.includes("/files");
const isCatalogs = pathname.includes("/catalogs");

const goToItem = (link?: string) => {
if (isPrepared()) {
Expand All @@ -47,6 +48,7 @@ const Menu = ({ isExpanded, isPinned = false, onTogglePin }: MenuProps) => {
isAgents={isAgents}
isTasks={isTasks}
isFiles={isFiles}
isCatalogs={isCatalogs}
onNavigate={goToItem}
/>

Expand Down
4 changes: 4 additions & 0 deletions components/Sidebar/SecondaryNav.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import AgentsNavItem from "./AgentsNavItem";
import TasksNavItem from "./TasksNavItem";
import FilesNavItem from "./FilesNavItem";
import CatalogsNavItem from "./CatalogsNavItem";

interface SecondaryNavProps {
isExpanded: boolean;
isAgents: boolean;
isTasks: boolean;
isFiles: boolean;
isCatalogs: boolean;
onNavigate: (path: string) => void;
}

Expand All @@ -15,9 +17,11 @@ const SecondaryNav = ({
isAgents,
isTasks,
isFiles,
isCatalogs,
onNavigate,
}: SecondaryNavProps) => (
<div className="flex flex-col gap-1 w-full mt-3">
<CatalogsNavItem isActive={isCatalogs} isExpanded={isExpanded} onClick={() => onNavigate("catalogs")} />
<AgentsNavItem isActive={isAgents} isExpanded={isExpanded} onClick={() => onNavigate("agents")} />
<TasksNavItem isActive={isTasks} isExpanded={isExpanded} onClick={() => onNavigate("tasks")} />
<FilesNavItem isActive={isFiles} isExpanded={isExpanded} onClick={() => onNavigate("files")} />
Expand Down
54 changes: 54 additions & 0 deletions components/Sidebar/__tests__/SecondaryNav.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// @vitest-environment jsdom
import React from "react";
import { fireEvent, render, screen } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import SecondaryNav from "@/components/Sidebar/SecondaryNav";

vi.mock("@/components/Agents/useAgentData", () => ({
useAgentData: () => ({ prefetchAgents: vi.fn() }),
}));

const renderNav = (overrides = {}) => {
const onNavigate = vi.fn();
render(
<SecondaryNav
isExpanded
isAgents={false}
isTasks={false}
isFiles={false}
isCatalogs={false}
onNavigate={onNavigate}
{...overrides}
/>,
);
return { onNavigate };
};

describe("SecondaryNav", () => {
// chat#1912 row 3: Catalogs is the valuation payoff surface and was
// reachable only by direct URL, so a customer could not find it from the
// app's own navigation. Reporter and quote live on the issue, not here.
it("links Catalogs alongside the other tools", () => {
renderNav();

expect(
screen.getByRole("button", { name: /view catalogs/i }),
).toBeDefined();
});

it("navigates to the catalogs route when Catalogs is clicked", () => {
const { onNavigate } = renderNav();

fireEvent.click(screen.getByRole("button", { name: /view catalogs/i }));

expect(onNavigate).toHaveBeenCalledWith("catalogs");
});

it("still links the pre-existing tools", () => {
renderNav();

expect(screen.getByRole("button", { name: /view agents/i })).toBeDefined();
expect(screen.getByRole("button", { name: /view tasks/i })).toBeDefined();
expect(screen.getByRole("button", { name: /view files/i })).toBeDefined();
});
});
Loading