From 799371e55523fcee5804b5e1902606441f955704 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 31 Aug 2026 15:50:33 +0000 Subject: [PATCH 1/2] =?UTF-8?q?cherry-pick=20of=20#28772=20failed=20?= =?UTF-8?q?=E2=80=94=20resolve=20conflicts=20manually?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick of 3d3b36ff893ba7bb84b46cc96b3a0f738c64eb8f onto release/2.37 had conflicts. To resolve: git fetch origin backport/28772-to-2.37 git checkout backport/28772-to-2.37 git cherry-pick -x -m1 3d3b36ff893ba7bb84b46cc96b3a0f738c64eb8f # resolve conflicts git push origin backport/28772-to-2.37 From ea65bd950a46d491c5c8f4cfb34cbe79321ce694 Mon Sep 17 00:00:00 2001 From: Ethan <39577870+ethanndickson@users.noreply.github.com> Date: Mon, 31 Aug 2026 17:49:57 +0200 Subject: [PATCH 2/2] fix(site): remove member-facing Models nav item (#28772) (cherry picked from commit 3d3b36ff893ba7bb84b46cc96b3a0f738c64eb8f) --- .../dashboard/DashboardLayout.stories.tsx | 79 ------------------- .../dashboard/Navbar/MobileMenu.stories.tsx | 36 +-------- .../modules/dashboard/Navbar/MobileMenu.tsx | 7 -- site/src/modules/dashboard/Navbar/Navbar.tsx | 6 -- .../dashboard/Navbar/NavbarView.stories.tsx | 34 -------- .../modules/dashboard/Navbar/NavbarView.tsx | 22 +----- 6 files changed, 2 insertions(+), 182 deletions(-) diff --git a/site/src/modules/dashboard/DashboardLayout.stories.tsx b/site/src/modules/dashboard/DashboardLayout.stories.tsx index d57b63f83f655..a4fb15928a8c4 100644 --- a/site/src/modules/dashboard/DashboardLayout.stories.tsx +++ b/site/src/modules/dashboard/DashboardLayout.stories.tsx @@ -5,15 +5,10 @@ import { reactRouterParameters, } from "storybook-addon-remix-react-router"; import { buildInfoKey } from "#/api/queries/buildInfo"; -import { chatModels } from "#/api/queries/chats"; import { deploymentStatsQueryKey } from "#/api/queries/deployment"; import { organizationsPermissions } from "#/api/queries/organizations"; import { updateCheckQueryKey } from "#/api/queries/updateCheck"; import type { UpdateCheckResponse } from "#/api/typesGenerated"; -import { - MockChatModel, - MockChatModelProviderDescriptor, -} from "#/testHelpers/chatModels"; import { MockBuildInfo, MockDefaultOrganization, @@ -55,17 +50,6 @@ const mcpServersRouter = reactRouterParameters({ ], }); -const modelSettingsRouter = reactRouterParameters({ - location: { path: "/" }, - routing: [ - { path: "/", useStoryElement: true }, - { - path: "/ai/settings/models", - element:

Organization models

, - }, - ], -}); - const meta: Meta = { title: "modules/dashboard/DashboardLayout", component: DashboardLayout, @@ -124,57 +108,6 @@ export const ForMember: Story = { }, }; -export const CustomOrganizationRoleCanOpenModels: Story = { - parameters: { - pixel: { matrix: pixelWithDesktop }, - user: MockUserMember, - permissions: MockNoPermissions, - reactRouter: modelSettingsRouter, - queries: [ - { key: buildInfoKey, data: MockBuildInfo }, - { key: updateCheckQueryKey, data: MockUpdateCheck }, - { key: deploymentStatsQueryKey, data: MockDeploymentStats }, - { - key: organizationsPermissions([MockDefaultOrganization.id]).queryKey, - data: { - [MockDefaultOrganization.id]: { - ...MockNoOrganizationPermissions, - viewChatModelConfigs: true, - }, - }, - }, - ], - }, - play: openModels, -}; - -export const ACLReadableMemberCanOpenModels: Story = { - parameters: { - pixel: { matrix: pixelWithDesktop }, - user: MockUserMember, - permissions: MockNoPermissions, - reactRouter: modelSettingsRouter, - queries: [ - { key: buildInfoKey, data: MockBuildInfo }, - { key: updateCheckQueryKey, data: MockUpdateCheck }, - { key: deploymentStatsQueryKey, data: MockDeploymentStats }, - { - key: chatModels(MockDefaultOrganization.id).queryKey, - data: { - models: [ - { - ...MockChatModel, - organization_id: MockDefaultOrganization.id, - }, - ], - providers: [MockChatModelProviderDescriptor], - }, - }, - ], - }, - play: openModels, -}; - export const CustomOrganizationRoleCanOpenMCPServers: Story = { parameters: { pixel: { matrix: pixelWithDesktop }, @@ -243,15 +176,3 @@ export const SkipToMainContent: Story = { await expect(main).toHaveFocus(); }, }; - -async function openModels({ canvasElement }: { canvasElement: HTMLElement }) { - const user = userEvent.setup(); - const canvas = within(canvasElement); - await expect( - canvas.queryByRole("button", { name: "Admin settings" }), - ).not.toBeInTheDocument(); - await user.click(canvas.getByRole("link", { name: "Models" })); - await expect( - await canvas.findByRole("heading", { name: "Organization models" }), - ).toBeInTheDocument(); -} diff --git a/site/src/modules/dashboard/Navbar/MobileMenu.stories.tsx b/site/src/modules/dashboard/Navbar/MobileMenu.stories.tsx index b7c5478a29a83..d8391c1f95845 100644 --- a/site/src/modules/dashboard/Navbar/MobileMenu.stories.tsx +++ b/site/src/modules/dashboard/Navbar/MobileMenu.stories.tsx @@ -1,7 +1,6 @@ import type { Meta, StoryObj } from "@storybook/react-vite"; import type { FC } from "react"; -import { expect, fn, userEvent, within } from "storybook/test"; -import { reactRouterParameters } from "storybook-addon-remix-react-router"; +import { fn, userEvent, within } from "storybook/test"; import { MockPrimaryWorkspaceProxy, MockProxyLatencies, @@ -43,7 +42,6 @@ const meta: Meta = { supportLinks: MockSupportLinks, onSignOut: fn(), isDefaultOpen: true, - canViewModels: false, adminPermissions: { canViewDeployment: true, canViewOrganizations: true, @@ -98,38 +96,6 @@ export const Member: Story = { }, }; -export const MemberWithModelAccess: Story = { - parameters: { - reactRouter: reactRouterParameters({ - location: { path: "/" }, - routing: [ - { path: "/", useStoryElement: true }, - { - path: "/ai/settings/models", - element:

Organization models

, - }, - ], - }), - }, - args: { - user: MockUserMember, - adminPermissions: {}, - canViewModels: true, - }, - play: async ({ canvasElement }) => { - const user = userEvent.setup(); - const canvas = within(canvasElement); - const body = within(canvasElement.ownerDocument.body); - await expect( - body.queryByRole("menuitem", { name: /admin settings/i }), - ).not.toBeInTheDocument(); - await user.click(body.getByRole("menuitem", { name: "Models" })); - await expect( - await canvas.findByRole("heading", { name: "Organization models" }), - ).toBeInTheDocument(); - }, -}; - export const ProxySettings: Story = { play: async ({ canvasElement }) => { const user = userEvent.setup(); diff --git a/site/src/modules/dashboard/Navbar/MobileMenu.tsx b/site/src/modules/dashboard/Navbar/MobileMenu.tsx index d09f925c2cc50..b8bd979a74b68 100644 --- a/site/src/modules/dashboard/Navbar/MobileMenu.tsx +++ b/site/src/modules/dashboard/Navbar/MobileMenu.tsx @@ -43,7 +43,6 @@ const itemStyles = { type MobileMenuProps = { proxyContextValue?: ProxyContextValue; - canViewModels: boolean; adminPermissions: AdminSettingsPermissions; user?: TypesGen.User; supportLinks?: readonly TypesGen.LinkConfig[]; @@ -53,7 +52,6 @@ type MobileMenuProps = { export const MobileMenu: FC = ({ adminPermissions, - canViewModels, proxyContextValue, user, supportLinks, @@ -89,11 +87,6 @@ export const MobileMenu: FC = ({ Agents - {canViewModels && ( - - Models - - )} diff --git a/site/src/modules/dashboard/Navbar/Navbar.tsx b/site/src/modules/dashboard/Navbar/Navbar.tsx index 4a0024011f660..e21feecc6732c 100644 --- a/site/src/modules/dashboard/Navbar/Navbar.tsx +++ b/site/src/modules/dashboard/Navbar/Navbar.tsx @@ -10,7 +10,6 @@ import { canViewDeploymentSettings, } from "#/modules/permissions"; import { useCanShareOrganizationMCPServers } from "#/pages/AISettingsPage/MCPServersPage/organizationSharing"; -import { useAccessibleModelOrganizations } from "#/pages/AISettingsPage/ModelsPage/organizationModels"; import { useFeatureVisibility } from "../useFeatureVisibility"; import { NavbarView } from "./NavbarView"; @@ -22,8 +21,6 @@ export const Navbar: React.FC = () => { const { user: me, permissions, signOut } = useAuthenticated(); const featureVisibility = useFeatureVisibility(); const proxyContextValue = useProxy(); - const accessibleModelOrgsQuery = - useAccessibleModelOrganizations(organizations); const canAccessAnyModel = canAccessAnyChatModelConfig(permissions); const canViewDeployment = canViewDeploymentSettings(permissions); @@ -51,8 +48,6 @@ export const Navbar: React.FC = () => { ); const canViewAISettings = canViewSiteWideAISettings || organizationMCPSharing.canShare; - const canViewModels = - !canViewAISettings && accessibleModelOrgsQuery.organizations.length > 0; const canCreateChat = permissions.createChat; const uniqueLinks = new Map(); @@ -76,7 +71,6 @@ export const Navbar: React.FC = () => { canViewAIBridge, canViewHealth, }} - canViewModels={canViewModels} canCreateChat={canCreateChat} proxyContextValue={proxyContextValue} /> diff --git a/site/src/modules/dashboard/Navbar/NavbarView.stories.tsx b/site/src/modules/dashboard/Navbar/NavbarView.stories.tsx index 563d9dbc4a4ac..09560b7636490 100644 --- a/site/src/modules/dashboard/Navbar/NavbarView.stories.tsx +++ b/site/src/modules/dashboard/Navbar/NavbarView.stories.tsx @@ -72,7 +72,6 @@ const meta: Meta = { canViewAIBridge: true, canViewHealth: true, }, - canViewModels: false, canCreateChat: true, supportLinks: [], }, @@ -328,39 +327,6 @@ export const ForUserWithoutOrganization: Story = { }, }; -export const ForMemberWithModelAccess: Story = { - parameters: { - pixel: { matrix: pixelWithDesktop }, - reactRouter: reactRouterParameters({ - location: { path: "/" }, - routing: [ - { path: "/", useStoryElement: true }, - { - path: "/ai/settings/models", - element:

Organization models

, - }, - ], - }), - }, - args: { - user: MockUserMember, - adminPermissions: {}, - canViewModels: true, - canCreateChat: false, - }, - play: async ({ canvasElement }) => { - const user = userEvent.setup(); - const canvas = within(canvasElement); - await expect( - canvas.queryByRole("button", { name: "Admin settings" }), - ).not.toBeInTheDocument(); - await user.click(canvas.getByRole("link", { name: "Models" })); - await expect( - await canvas.findByRole("heading", { name: "Organization models" }), - ).toBeInTheDocument(); - }, -}; - export const ForMember: Story = { args: { user: MockUserMember, diff --git a/site/src/modules/dashboard/Navbar/NavbarView.tsx b/site/src/modules/dashboard/Navbar/NavbarView.tsx index a51df951659f4..7167570c42477 100644 --- a/site/src/modules/dashboard/Navbar/NavbarView.tsx +++ b/site/src/modules/dashboard/Navbar/NavbarView.tsx @@ -33,7 +33,6 @@ interface NavbarViewProps { onSignOut: () => void; adminPermissions: AdminSettingsPermissions; canCreateChat: boolean; - canViewModels: boolean; proxyContextValue?: ProxyContextValue; } @@ -50,7 +49,6 @@ export const NavbarView: FC = ({ onSignOut, adminPermissions, canCreateChat, - canViewModels, proxyContextValue, }) => { const prerelease = getPrereleaseFlag(buildInfo); @@ -82,7 +80,6 @@ export const NavbarView: FC = ({ @@ -148,7 +145,6 @@ export const NavbarView: FC = ({
= ({ interface NavItemsProps { className?: string; user: TypesGen.User; - canViewModels: boolean; canCreateChat: boolean; } -const NavItems: FC = ({ - className, - user, - canCreateChat, - canViewModels, -}) => { +const NavItems: FC = ({ className, user, canCreateChat }) => { const location = useLocation(); return ( @@ -197,16 +187,6 @@ const NavItems: FC = ({ Templates - {canViewModels && ( - - cn(linkStyles.default, { [linkStyles.active]: isActive }) - } - to="/ai/settings/models" - > - Models - - )} {canCreateChat && ( {