diff --git a/apps/desktop/src/components/editor/EditorSettingsDialog.vue b/apps/desktop/src/components/editor/EditorSettingsDialog.vue index 0859224c9d..d54ce39f9c 100644 --- a/apps/desktop/src/components/editor/EditorSettingsDialog.vue +++ b/apps/desktop/src/components/editor/EditorSettingsDialog.vue @@ -7730,29 +7730,44 @@ onUnmounted(() => {

{{ t("settings.tableOpenSortDescription") }}

- +
- +
- +
diff --git a/apps/desktop/src/components/settings/McpDatabaseScopePicker.vue b/apps/desktop/src/components/settings/McpDatabaseScopePicker.vue index face0c23dc..6a94064e33 100644 --- a/apps/desktop/src/components/settings/McpDatabaseScopePicker.vue +++ b/apps/desktop/src/components/settings/McpDatabaseScopePicker.vue @@ -5,6 +5,7 @@ import { useI18n } from "vue-i18n"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; import { Badge } from "@/components/ui/badge"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import { listDatabases, mongoListDatabases, redisListDatabases } from "@/lib/backend/api"; import { useConnectionStore } from "@/stores/connectionStore"; import type { McpConnectionPolicy } from "@/stores/settingsStore"; @@ -220,12 +221,15 @@ watch(databasePageCount, () => setDatabasePage(databasePage.value));

{{ t("settings.mcpDatabaseScopeAllowedConnections") }}

- +
+ {{ t("settings.mcpPerPage") }} + +
diff --git a/apps/desktop/src/components/settings/McpResourceScopePicker.vue b/apps/desktop/src/components/settings/McpResourceScopePicker.vue index 97a53e8b09..338b71fb0d 100644 --- a/apps/desktop/src/components/settings/McpResourceScopePicker.vue +++ b/apps/desktop/src/components/settings/McpResourceScopePicker.vue @@ -5,6 +5,7 @@ import { useI18n } from "vue-i18n"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Input } from "@/components/ui/input"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; import type { ConnectionConfig, SidebarLayout, SidebarOrderEntry } from "@/types/database"; type ScopeMode = "all" | "custom"; @@ -325,32 +326,29 @@ function connectionPolicyMode(connectionId: string): ExecutionMode | "inherit" {

{{ node.type === "group" ? node.name : node.connection.name }}

{{ node.connection.db_type }} ยท {{ node.connection.host || node.connection.database || node.id }}

- - + + + + {{ selectedAncestor(node) ? t("settings.mcpGroupPolicyInherit") : t("settings.mcpConnectionPolicyInherit") }} + {{ t("settings.mcpConnectionPolicyReadOnly") }} + {{ t("settings.mcpConnectionPolicySafeWrite") }} + {{ t("settings.mcpConnectionPolicyHighRiskWrite") }} + + {{ t("settings.mcpResourceScopeInherited", { group: groupLabel(selectedAncestor(node)!) }) }} {{ t("settings.mcpResourceScopeDynamic") }} {{ t("settings.mcpResourceScopePartial") }} diff --git a/apps/desktop/src/components/settings/__tests__/McpDatabaseScopePicker.spec.ts b/apps/desktop/src/components/settings/__tests__/McpDatabaseScopePicker.spec.ts index b0fc5c6535..37f4dc9959 100644 --- a/apps/desktop/src/components/settings/__tests__/McpDatabaseScopePicker.spec.ts +++ b/apps/desktop/src/components/settings/__tests__/McpDatabaseScopePicker.spec.ts @@ -42,6 +42,13 @@ async function passthroughComponent() { } vi.mock("@/components/ui/button", async () => ({ Button: await passthroughComponent() })); vi.mock("@/components/ui/badge", async () => ({ Badge: await passthroughComponent() })); +vi.mock("@/components/ui/select", async () => ({ + Select: await passthroughComponent(), + SelectContent: await passthroughComponent(), + SelectItem: await passthroughComponent(), + SelectTrigger: await passthroughComponent(), + SelectValue: await passthroughComponent(), +})); vi.mock("@/components/ui/input", async () => { const { defineComponent, h } = await import("vue"); const Input = defineComponent({ diff --git a/apps/desktop/src/components/settings/__tests__/McpResourceScopePicker.spec.ts b/apps/desktop/src/components/settings/__tests__/McpResourceScopePicker.spec.ts index 480484a68b..1d70b1817b 100644 --- a/apps/desktop/src/components/settings/__tests__/McpResourceScopePicker.spec.ts +++ b/apps/desktop/src/components/settings/__tests__/McpResourceScopePicker.spec.ts @@ -19,6 +19,16 @@ vi.mock("@lucide/vue", async () => { vi.mock("@/components/ui/badge", async () => ({ Badge: (await import("@/components/grid/__tests__/vueHostHarness")).createPassthroughStub("Badge", "span") })); vi.mock("@/components/ui/button", async () => ({ Button: (await import("@/components/grid/__tests__/vueHostHarness")).createPassthroughStub("Button", "button") })); vi.mock("@/components/ui/input", async () => ({ Input: (await import("@/components/grid/__tests__/vueHostHarness")).createPassthroughStub("Input", "input") })); +vi.mock("@/components/ui/select", async () => { + const { createPassthroughStub } = await import("@/components/grid/__tests__/vueHostHarness"); + return { + Select: createPassthroughStub("Select", "div"), + SelectContent: createPassthroughStub("SelectContent", "div"), + SelectItem: createPassthroughStub("SelectItem", "div"), + SelectTrigger: createPassthroughStub("SelectTrigger", "button"), + SelectValue: createPassthroughStub("SelectValue", "span"), + }; +}); import McpResourceScopePicker from "@/components/settings/McpResourceScopePicker.vue"; diff --git a/apps/desktop/src/components/settings/__tests__/SettingsSelectConsistency.spec.ts b/apps/desktop/src/components/settings/__tests__/SettingsSelectConsistency.spec.ts new file mode 100644 index 0000000000..dcaadb1b4e --- /dev/null +++ b/apps/desktop/src/components/settings/__tests__/SettingsSelectConsistency.spec.ts @@ -0,0 +1,15 @@ +import { readFileSync } from "node:fs"; +import { describe, expect, it } from "vitest"; + +const settingsSources = ["../../editor/EditorSettingsDialog.vue", "../../editor/SqlFormatterSettingsPanel.vue", "../McpAuthorizationStepper.vue", "../McpDatabaseScopePicker.vue", "../McpResourceScopePicker.vue", "../SettingsTransferPanel.vue"].map((path) => ({ + path, + source: readFileSync(new URL(path, import.meta.url), "utf8"), +})); + +describe("settings select styling", () => { + it("uses the shared Select component instead of native select controls", () => { + for (const { path, source } of settingsSources) { + expect(source, path).not.toMatch(/)/); + } + }); +});