refactor(ui): colocate 11 route segments' components into _components/ (#32704)

Colocation follow-up to the App Router migration: move each page's owned
components out of the shared src/components dump and into its route segment's
_components/ folder, draining the shared bucket. Convention: a component used
by exactly one segment goes in that segment's _components/ (private, matching
Next's _ route-exclusion); a component shared by 2+ segments stays in
@/components. No new _shared/ folder.

Rename-in-place (segment already had a local components/ folder):
- api-reference (also relocates the shared CodeBlock, used by playground and
  cost-tracking, to @/components/CodeBlock)
- memory, budgets, access-groups
- caching, projects, guardrails-monitor

Extract from src/components (page view lived in the shared dump):
- AdminPanel -> admin-panel, organizations -> organizations,
  general_settings -> router-settings, usage -> old-usage

Each folder/view was verified to have no importer other than its own page
(cross-checked across src, tests, and e2e_tests). Relative imports inside moved
single files are rewritten to absolute @/components/*; colocated tests move with
their subject and have their vi.mock paths rewritten to match. Grandfathered
lint suppressions (tremor, react-hooks, and similar, all pre-existing) are
re-keyed to the new paths with counts unchanged. No behavior change.
This commit is contained in:
ryan-crabbe-berri 2026-07-09 17:43:33 -07:00 • committed by GitHub
parent 68a4ca7247
commit 65d90fd5cf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
78 changed files with 91 additions and 84 deletions

View file

@ -4,32 +4,32 @@
"count": 1
}
},
"src/app/(dashboard)/api-reference/APIReferenceView.tsx": {
"src/app/(dashboard)/api-reference/_components/APIReferenceView.tsx": {
"no-restricted-imports": {
"count": 1
}
},
"src/app/(dashboard)/budgets/components/budget_modal.tsx": {
"src/app/(dashboard)/budgets/_components/budget_modal.tsx": {
"no-restricted-imports": {
"count": 1
}
},
"src/app/(dashboard)/budgets/components/budget_panel.test.tsx": {
"src/app/(dashboard)/budgets/_components/budget_panel.test.tsx": {
"unused-imports/no-unused-imports": {
"count": 2
}
},
"src/app/(dashboard)/budgets/components/budget_panel.tsx": {
"src/app/(dashboard)/budgets/_components/budget_panel.tsx": {
"no-restricted-imports": {
"count": 1
}
},
"src/app/(dashboard)/budgets/components/edit_budget_modal.tsx": {
"src/app/(dashboard)/budgets/_components/edit_budget_modal.tsx": {
"no-restricted-imports": {
"count": 1
}
},
"src/app/(dashboard)/caching/components/cache_dashboard.tsx": {
"src/app/(dashboard)/caching/_components/cache_dashboard.tsx": {
"no-restricted-imports": {
"count": 1
},
@ -40,17 +40,17 @@
"count": 2
}
},
"src/app/(dashboard)/caching/components/cache_health.tsx": {
"src/app/(dashboard)/caching/_components/cache_health.tsx": {
"no-restricted-imports": {
"count": 1
}
},
"src/app/(dashboard)/caching/components/cache_settings/RedisTypeSelector.tsx": {
"src/app/(dashboard)/caching/_components/cache_settings/RedisTypeSelector.tsx": {
"no-restricted-imports": {
"count": 1
}
},
"src/app/(dashboard)/caching/components/cache_settings/index.tsx": {
"src/app/(dashboard)/caching/_components/cache_settings/index.tsx": {
"no-restricted-imports": {
"count": 1
},
@ -136,32 +136,32 @@
"count": 2
}
},
"src/app/(dashboard)/guardrails-monitor/components/EvaluationSettingsModal.tsx": {
"src/app/(dashboard)/guardrails-monitor/_components/EvaluationSettingsModal.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/guardrails-monitor/components/GuardrailDetail.tsx": {
"src/app/(dashboard)/guardrails-monitor/_components/GuardrailDetail.tsx": {
"no-nested-ternary": {
"count": 3
}
},
"src/app/(dashboard)/guardrails-monitor/components/GuardrailsMonitorView.tsx": {
"src/app/(dashboard)/guardrails-monitor/_components/GuardrailsMonitorView.tsx": {
"no-restricted-imports": {
"count": 1
}
},
"src/app/(dashboard)/guardrails-monitor/components/GuardrailsOverview.tsx": {
"src/app/(dashboard)/guardrails-monitor/_components/GuardrailsOverview.tsx": {
"no-nested-ternary": {
"count": 8
}
},
"src/app/(dashboard)/guardrails-monitor/components/ScoreChart.test.tsx": {
"src/app/(dashboard)/guardrails-monitor/_components/ScoreChart.test.tsx": {
"react/display-name": {
"count": 1
}
},
"src/app/(dashboard)/guardrails-monitor/components/ScoreChart.tsx": {
"src/app/(dashboard)/guardrails-monitor/_components/ScoreChart.tsx": {
"no-restricted-imports": {
"count": 1
}
@ -326,7 +326,7 @@
"count": 2
}
},
"src/app/(dashboard)/memory/components/MemoryView.tsx": {
"src/app/(dashboard)/memory/_components/MemoryView.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
@ -522,7 +522,7 @@
"count": 1
}
},
"src/app/(dashboard)/projects/components/ProjectDetailsPage.tsx": {
"src/app/(dashboard)/projects/_components/ProjectDetailsPage.tsx": {
"no-nested-ternary": {
"count": 3
},
@ -530,17 +530,17 @@
"count": 1
}
},
"src/app/(dashboard)/projects/components/ProjectKeysSection.tsx": {
"src/app/(dashboard)/projects/_components/ProjectKeysSection.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
},
"src/app/(dashboard)/projects/components/ProjectModals/ProjectBaseForm.tsx": {
"src/app/(dashboard)/projects/_components/ProjectModals/ProjectBaseForm.tsx": {
"react-hooks/set-state-in-effect": {
"count": 2
}
},
"src/app/(dashboard)/projects/components/ProjectsPage.tsx": {
"src/app/(dashboard)/projects/_components/ProjectsPage.tsx": {
"react-hooks/set-state-in-effect": {
"count": 1
}
@ -851,7 +851,7 @@
"count": 1
}
},
"src/components/AdminPanel.tsx": {
"src/app/(dashboard)/admin-panel/_components/AdminPanel.tsx": {
"no-restricted-imports": {
"count": 1
},
@ -1520,7 +1520,7 @@
"count": 1
}
},
"src/components/general_settings.tsx": {
"src/app/(dashboard)/router-settings/_components/general_settings.tsx": {
"no-nested-ternary": {
"count": 3
},
@ -2028,7 +2028,7 @@
"count": 1
}
},
"src/components/organizations.tsx": {
"src/app/(dashboard)/organizations/_components/organizations.tsx": {
"no-restricted-imports": {
"count": 1
}
@ -2371,7 +2371,7 @@
"count": 1
}
},
"src/components/usage.tsx": {
"src/app/(dashboard)/old-usage/_components/usage.tsx": {
"no-restricted-imports": {
"count": 2
},

View file

@ -1,6 +1,6 @@
"use client";
import { AccessGroupsPage } from "./components/AccessGroupsPage";
import { AccessGroupsPage } from "./_components/AccessGroupsPage";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
export default function AccessGroups() {

View file

@ -8,34 +8,34 @@ const mockGetAllowedIPs = vi.fn();
const mockAddAllowedIP = vi.fn();
const mockDeleteAllowedIP = vi.fn();
vi.mock("./networking", () => ({
vi.mock("@/components/networking", () => ({
getSSOSettings: (...args: unknown[]) => mockGetSSOSettings(...args),
getAllowedIPs: (...args: unknown[]) => mockGetAllowedIPs(...args),
addAllowedIP: (...args: unknown[]) => mockAddAllowedIP(...args),
deleteAllowedIP: (...args: unknown[]) => mockDeleteAllowedIP(...args),
}));
vi.mock("./constants", () => ({
vi.mock("@/components/constants", () => ({
useBaseUrl: () => "http://localhost:4000",
}));
vi.mock("./Settings/AdminSettings/SSOSettings/SSOSettings", () => ({
vi.mock("@/components/Settings/AdminSettings/SSOSettings/SSOSettings", () => ({
default: () => <div>SSO Settings</div>,
}));
vi.mock("./Settings/AdminSettings/UISettings/UISettings", () => ({
vi.mock("@/components/Settings/AdminSettings/UISettings/UISettings", () => ({
default: () => <div>UI Settings</div>,
}));
vi.mock("./SCIM", () => ({
vi.mock("@/components/SCIM", () => ({
default: () => <div>SCIM Config</div>,
}));
vi.mock("./SSOModals", () => ({
vi.mock("@/components/SSOModals", () => ({
default: () => <div>SSO Modals</div>,
}));
vi.mock("./UIAccessControlForm", () => ({
vi.mock("@/components/UIAccessControlForm", () => ({
default: () => <div>UI Access Control Form</div>,
}));

View file

@ -16,18 +16,18 @@ import {
} from "@tremor/react";
import { Alert, Button as Button2, Form, Input, Modal, Space, Tabs, Typography } from "antd";
import React, { useEffect, useState } from "react";
import NewBadge from "./common_components/NewBadge";
import { useBaseUrl } from "./constants";
import NotificationsManager from "./molecules/notifications_manager";
import { addAllowedIP, deleteAllowedIP, getAllowedIPs, getSSOSettings } from "./networking";
import SCIMConfig from "./SCIM";
import LoggingSettings from "./Settings/AdminSettings/LoggingSettings/LoggingSettings";
import SSOSettings from "./Settings/AdminSettings/SSOSettings/SSOSettings";
import UISettings from "./Settings/AdminSettings/UISettings/UISettings";
import HashicorpVault from "./Settings/AdminSettings/HashicorpVault/HashicorpVault";
import PluginSettings from "./Settings/AdminSettings/PluginSettings/PluginSettings";
import SSOModals from "./SSOModals";
import UIAccessControlForm from "./UIAccessControlForm";
import NewBadge from "@/components/common_components/NewBadge";
import { useBaseUrl } from "@/components/constants";
import NotificationsManager from "@/components/molecules/notifications_manager";
import { addAllowedIP, deleteAllowedIP, getAllowedIPs, getSSOSettings } from "@/components/networking";
import SCIMConfig from "@/components/SCIM";
import LoggingSettings from "@/components/Settings/AdminSettings/LoggingSettings/LoggingSettings";
import SSOSettings from "@/components/Settings/AdminSettings/SSOSettings/SSOSettings";
import UISettings from "@/components/Settings/AdminSettings/UISettings/UISettings";
import HashicorpVault from "@/components/Settings/AdminSettings/HashicorpVault/HashicorpVault";
import PluginSettings from "@/components/Settings/AdminSettings/PluginSettings/PluginSettings";
import SSOModals from "@/components/SSOModals";
import UIAccessControlForm from "@/components/UIAccessControlForm";
const { Title, Paragraph, Text } = Typography;

View file

@ -1,6 +1,6 @@
"use client";
import AdminPanel from "@/components/AdminPanel";
import AdminPanel from "./_components/AdminPanel";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import useProxySettings from "@/app/(dashboard)/hooks/proxySettings/useProxySettings";

View file

@ -2,7 +2,7 @@ import { render } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import APIReferenceView from "./APIReferenceView";
vi.mock("./components/CodeBlock", () => ({
vi.mock("@/components/CodeBlock", () => ({
__esModule: true,
default: ({ code }: { code: string }) => <pre data-testid="api-reference-code-block">{code}</pre>,
}));

View file

@ -1,8 +1,8 @@
"use client";
import React from "react";
import { Text, Tab, TabGroup, TabList, TabPanel, TabPanels, Grid } from "@tremor/react";
import CodeBlock from "./components/CodeBlock";
import DocLink from "@/app/(dashboard)/api-reference/components/DocLink";
import CodeBlock from "@/components/CodeBlock";
import DocLink from "./DocLink";
interface ApiRefProps {
proxySettings: {

View file

@ -1,6 +1,6 @@
"use client";
import APIReferenceView from "@/app/(dashboard)/api-reference/APIReferenceView";
import APIReferenceView from "./_components/APIReferenceView";
import { DeprecationBanner } from "@/components/DeprecationBanner";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
import useProxySettings from "@/app/(dashboard)/hooks/proxySettings/useProxySettings";

View file

@ -1,6 +1,6 @@
"use client";
import BudgetPanel from "./components/budget_panel";
import BudgetPanel from "./_components/budget_panel";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
export default function Budgets() {

View file

@ -1,6 +1,6 @@
"use client";
import CacheDashboard from "./components/cache_dashboard";
import CacheDashboard from "./_components/cache_dashboard";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
export default function Caching() {

View file

@ -5,7 +5,7 @@ import userEvent from "@testing-library/user-event";
import { renderWithProviders } from "../../../../../tests/test-utils";
import HowItWorks from "./how_it_works";
vi.mock("@/app/(dashboard)/api-reference/components/CodeBlock", () => ({
vi.mock("@/components/CodeBlock", () => ({
default: ({ code }: { code: string }) => <pre data-testid="code-block">{code}</pre>,
}));

View file

@ -1,6 +1,6 @@
import React, { useState, useMemo } from "react";
import { Text, TextInput } from "@tremor/react";
import CodeBlock from "@/app/(dashboard)/api-reference/components/CodeBlock";
import CodeBlock from "@/components/CodeBlock";
const HowItWorks: React.FC = () => {
const [responseCost, setResponseCost] = useState("");

View file

@ -1,6 +1,6 @@
"use client";
import GuardrailsMonitorView from "./components/GuardrailsMonitorView";
import GuardrailsMonitorView from "./_components/GuardrailsMonitorView";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
export default function GuardrailsMonitor() {

View file

@ -1,6 +1,6 @@
"use client";
import { MemoryView } from "./components/MemoryView";
import { MemoryView } from "./_components/MemoryView";
import { DeprecationBanner } from "@/components/DeprecationBanner";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";

View file

@ -14,9 +14,9 @@ import {
import React, { useState, useEffect } from "react";
import ViewUserSpend from "./view_user_spend";
import { ProxySettings } from "./user_dashboard";
import UsageDatePicker from "./shared/usage_date_picker";
import ViewUserSpend from "@/components/view_user_spend";
import { ProxySettings } from "@/components/user_dashboard";
import UsageDatePicker from "@/components/shared/usage_date_picker";
import {
Grid,
Col,
@ -48,8 +48,8 @@ import {
adminGlobalActivity,
adminGlobalActivityPerModel,
getProxyUISettings,
} from "./networking";
import TopKeyView from "./UsagePage/components/EntityUsage/TopKeyView";
} from "@/components/networking";
import TopKeyView from "@/components/UsagePage/components/EntityUsage/TopKeyView";
import { MoneyCell } from "@/components/shared/table_cells";
import { formatNumberWithCommas } from "@/utils/dataUtils";

View file

@ -1,6 +1,6 @@
"use client";
import Usage from "@/components/usage";
import Usage from "./_components/usage";
import { DeprecationBanner } from "@/components/DeprecationBanner";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";

View file

@ -3,11 +3,11 @@ import { render } from "@testing-library/react";
import React from "react";
import { describe, expect, it, vi } from "vitest";
vi.mock("./vector_store_management/VectorStoreSelector", () => ({
vi.mock("@/components/vector_store_management/VectorStoreSelector", () => ({
__esModule: true,
default: () => null,
}));
vi.mock("./mcp_server_management/MCPServerSelector", () => ({
vi.mock("@/components/mcp_server_management/MCPServerSelector", () => ({
__esModule: true,
default: () => null,
}));

View file

@ -28,16 +28,21 @@ import { Form, Input, Modal, Select as Select2, Tooltip } from "antd";
import { useQueryClient } from "@tanstack/react-query";
import React, { useState } from "react";
import { DateCell, IdCell, MoneyCell } from "@/components/shared/table_cells";
import DeleteResourceModal from "./common_components/DeleteResourceModal";
import TableIconActionButton from "./common_components/IconActionButton/TableIconActionButtons/TableIconActionButton";
import { getModelDisplayName } from "./key_team_helpers/fetch_available_models_team_key";
import MCPServerSelector from "./mcp_server_management/MCPServerSelector";
import { ModelSelect } from "./ModelSelect/ModelSelect";
import NotificationsManager from "./molecules/notifications_manager";
import { Organization, organizationCreateCall, organizationDeleteCall, organizationListCall } from "./networking";
import OrganizationInfoView from "./organization/organization_view";
import NumericalInput from "./shared/numerical_input";
import VectorStoreSelector from "./vector_store_management/VectorStoreSelector";
import DeleteResourceModal from "@/components/common_components/DeleteResourceModal";
import TableIconActionButton from "@/components/common_components/IconActionButton/TableIconActionButtons/TableIconActionButton";
import { getModelDisplayName } from "@/components/key_team_helpers/fetch_available_models_team_key";
import MCPServerSelector from "@/components/mcp_server_management/MCPServerSelector";
import { ModelSelect } from "@/components/ModelSelect/ModelSelect";
import NotificationsManager from "@/components/molecules/notifications_manager";
import {
Organization,
organizationCreateCall,
organizationDeleteCall,
organizationListCall,
} from "@/components/networking";
import OrganizationInfoView from "@/components/organization/organization_view";
import NumericalInput from "@/components/shared/numerical_input";
import VectorStoreSelector from "@/components/vector_store_management/VectorStoreSelector";
interface OrganizationsTableProps {
userRole: string;

View file

@ -1,6 +1,6 @@
"use client";
import OrganizationsTable from "@/components/organizations";
import OrganizationsTable from "./_components/organizations";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
export default function OrganizationsPage() {

View file

@ -11,7 +11,7 @@ import {
} from "@ant-design/icons";
import { Button, Input, Modal, Select, Spin, Tabs } from "antd";
import React, { useCallback, useEffect, useState } from "react";
import CodeBlock from "@/app/(dashboard)/api-reference/components/CodeBlock";
import CodeBlock from "@/components/CodeBlock";
import NotificationsManager from "@/components/molecules/notifications_manager";
import {
keyCreateCall,

View file

@ -1,6 +1,6 @@
"use client";
import { ProjectsPage } from "./components/ProjectsPage";
import { ProjectsPage } from "./_components/ProjectsPage";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
export default function Projects() {

View file

@ -13,14 +13,14 @@ import {
Switch,
} from "@tremor/react";
import { TabPanel, TabPanels, TabGroup, TabList, Tab } from "@tremor/react";
import { getGeneralSettingsCall, updateConfigFieldSetting, deleteConfigFieldSetting } from "./networking";
import { getGeneralSettingsCall, updateConfigFieldSetting, deleteConfigFieldSetting } from "@/components/networking";
import { InputNumber } from "antd";
import { TrashIcon } from "@heroicons/react/outline";
import { StatusBadge } from "@/components/shared/table_cells";
import RouterSettings from "./router_settings";
import Fallbacks from "./Settings/RouterSettings/Fallbacks/Fallbacks";
import RoutingGroups from "./routing_groups";
import RouterSettings from "@/components/router_settings";
import Fallbacks from "@/components/Settings/RouterSettings/Fallbacks/Fallbacks";
import RoutingGroups from "@/components/routing_groups";
interface GeneralSettingsPageProps {
accessToken: string | null;
userRole: string | null;

View file

@ -1,6 +1,6 @@
"use client";
import GeneralSettings from "@/components/general_settings";
import GeneralSettings from "./_components/general_settings";
import useAuthorized from "@/app/(dashboard)/hooks/useAuthorized";
export default function RouterSettingsPage() {

View file

@ -108,13 +108,15 @@ vi.mock("@/components/navbar", () => ({ default: stub("navbar") }));
vi.mock("@/components/user_dashboard", () => ({ default: stub("user-dashboard") }));
vi.mock("@/components/templates/model_dashboard", () => ({ default: stub("model-dashboard") }));
vi.mock("@/components/teams", () => ({ default: stub("teams") }));
vi.mock("@/components/organizations", () => ({
vi.mock("@/app/(dashboard)/organizations/_components/organizations", () => ({
default: stub("organizations"),
fetchOrganizations: vi.fn(), // consumed in effects
}));
vi.mock("@/components/admins", () => ({ default: stub("admin-panel") }));
vi.mock("@/components/settings", () => ({ default: stub("settings") }));
vi.mock("@/components/general_settings", () => ({ default: stub("general-settings") }));
vi.mock("@/app/(dashboard)/router-settings/_components/general_settings", () => ({
default: stub("general-settings"),
}));
vi.mock("@/components/pass_through_settings", () => ({ default: stub("pass-through-settings") }));
vi.mock("@/components/budgets/budget_panel", () => ({ default: stub("budget-panel") }));
vi.mock("@/components/view_logs", () => ({ default: stub("spend-logs") }));
@ -123,7 +125,7 @@ vi.mock("@/components/new_usage", () => ({ default: stub("new-usage") }));
vi.mock("@/components/api_ref", () => ({ default: stub("api-ref") }));
vi.mock("@/components/chat_ui/ChatUI", () => ({ default: stub("chat-ui") }));
vi.mock("@/components/leftnav", () => ({ default: stub("sidebar") }));
vi.mock("@/components/usage", () => ({ default: stub("usage") }));
vi.mock("@/app/(dashboard)/old-usage/_components/usage", () => ({ default: stub("usage") }));
vi.mock("@/components/cache_dashboard", () => ({ default: stub("cache-dashboard") }));
vi.mock("@/components/guardrails", () => ({ default: stub("guardrails") }));
vi.mock("@/components/prompts", () => ({ default: stub("prompts") }));