feat(ui): i18n for permissions displays

This commit is contained in:
吹雪 2026-06-11 05:48:58 +09:00
parent c8228990a8
commit 17e3d704df
5 changed files with 71 additions and 13 deletions

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
import { Text, Badge } from "@tremor/react";
import { UserGroupIcon } from "@heroicons/react/outline";
import { Tooltip } from "antd";
import { useTranslation } from "react-i18next";
import { getAgentsList } from "../networking";
interface Agent {
@ -18,6 +19,7 @@ interface AgentPermissionsProps {
}
export function AgentPermissions({ agents, agentAccessGroups = [], accessToken }: AgentPermissionsProps) {
const { t } = useTranslation();
const [agentDetails, setAgentDetails] = useState<Agent[]>([]);
// Fetch agent details when component mounts
@ -58,7 +60,7 @@ export function AgentPermissions({ agents, agentAccessGroups = [], accessToken }
<div className="space-y-3">
<div className="flex items-center gap-2">
<UserGroupIcon className="h-4 w-4 text-purple-600" />
<Text className="font-semibold text-gray-900">Agents</Text>
<Text className="font-semibold text-gray-900">{t("permissions.agentPermissions.title")}</Text>
<Badge color="purple" size="xs">
{totalCount}
</Badge>
@ -71,7 +73,10 @@ export function AgentPermissions({ agents, agentAccessGroups = [], accessToken }
<div className="flex items-center gap-3 py-2 px-3 rounded-lg border border-gray-200 bg-white">
<div className="flex items-center gap-2 flex-1 min-w-0">
{item.type === "agent" ? (
<Tooltip title={`Full ID: ${item.value}`} placement="top">
<Tooltip
title={t("permissions.agentPermissions.fullIdTooltip", { id: item.value })}
placement="top"
>
<div className="inline-flex items-center gap-2 min-w-0">
<span className="inline-block w-1.5 h-1.5 bg-purple-500 rounded-full flex-shrink-0"></span>
<span className="text-sm font-medium text-gray-900 truncate">
@ -84,7 +89,7 @@ export function AgentPermissions({ agents, agentAccessGroups = [], accessToken }
<span className="inline-block w-1.5 h-1.5 bg-green-500 rounded-full flex-shrink-0"></span>
<span className="text-sm font-medium text-gray-900 truncate">{item.value}</span>
<span className="ml-1 px-1.5 py-0.5 text-[9px] font-semibold text-green-600 bg-green-50 border border-green-200 rounded uppercase tracking-wide flex-shrink-0">
Group
{t("permissions.agentPermissions.groupBadge")}
</span>
</div>
)}
@ -96,7 +101,7 @@ export function AgentPermissions({ agents, agentAccessGroups = [], accessToken }
) : (
<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-gray-50 border border-gray-200">
<UserGroupIcon className="h-4 w-4 text-gray-400" />
<Text className="text-gray-500 text-sm">No agents or access groups configured</Text>
<Text className="text-gray-500 text-sm">{t("permissions.agentPermissions.empty")}</Text>
</div>
)}
</div>

View file

@ -2,6 +2,7 @@ import React, { useState, useEffect } from "react";
import { Text, Badge } from "@tremor/react";
import { ServerIcon, ChevronDownIcon, ChevronRightIcon } from "@heroicons/react/outline";
import { Tooltip } from "antd";
import { useTranslation } from "react-i18next";
import { fetchMCPServers, fetchMCPToolsets } from "../networking";
import { MCPServer, MCPToolset } from "../mcp_tools/types";
@ -20,6 +21,7 @@ export function MCPServerPermissions({
mcpToolsets = [],
accessToken,
}: MCPServerPermissionsProps) {
const { t } = useTranslation();
const [mcpServerDetails, setMCPServerDetails] = useState<MCPServer[]>([]);
const [toolsetDetails, setToolsetDetails] = useState<MCPToolset[]>([]);
const [expandedServers, setExpandedServers] = useState<Set<string>>(new Set());
@ -105,7 +107,7 @@ export function MCPServerPermissions({
<div className="space-y-3">
<div className="flex items-center gap-2">
<ServerIcon className="h-4 w-4 text-blue-600" />
<Text className="font-semibold text-gray-900">MCP Servers</Text>
<Text className="font-semibold text-gray-900">{t("permissions.mcpServerPermissions.title")}</Text>
<Badge color="blue" size="xs">
{totalCount}
</Badge>
@ -128,7 +130,10 @@ export function MCPServerPermissions({
>
<div className="flex items-center gap-2 flex-1 min-w-0">
{item.type === "server" ? (
<Tooltip title={`Full ID: ${item.value}`} placement="top">
<Tooltip
title={t("permissions.mcpServerPermissions.fullIdTooltip", { id: item.value })}
placement="top"
>
<div className="inline-flex items-center gap-2 min-w-0">
<span className="inline-block w-1.5 h-1.5 bg-blue-500 rounded-full flex-shrink-0"></span>
<span className="text-sm font-medium text-gray-900 truncate">
@ -141,7 +146,7 @@ export function MCPServerPermissions({
<span className="inline-block w-1.5 h-1.5 bg-green-500 rounded-full flex-shrink-0"></span>
<span className="text-sm font-medium text-gray-900 truncate">{item.value}</span>
<span className="ml-1 px-1.5 py-0.5 text-[9px] font-semibold text-green-600 bg-green-50 border border-green-200 rounded uppercase tracking-wide flex-shrink-0">
Group
{t("permissions.mcpServerPermissions.groupBadge")}
</span>
</div>
)}
@ -150,7 +155,9 @@ export function MCPServerPermissions({
{hasToolRestrictions && (
<div className="flex items-center gap-1 flex-shrink-0 whitespace-nowrap">
<span className="text-xs font-medium text-gray-600">{toolsForServer.length}</span>
<span className="text-xs text-gray-500">{toolsForServer.length === 1 ? "tool" : "tools"}</span>
<span className="text-xs text-gray-500">
{t("permissions.mcpServerPermissions.toolCount", { count: toolsForServer.length })}
</span>
{isExpanded ? (
<ChevronDownIcon className="h-3.5 w-3.5 text-gray-400 ml-0.5" />
) : (
@ -200,13 +207,15 @@ export function MCPServerPermissions({
{detail?.toolset_name ?? toolsetId}
</span>
<span className="ml-1 px-1.5 py-0.5 text-[9px] font-semibold text-purple-600 bg-purple-50 border border-purple-200 rounded uppercase tracking-wide flex-shrink-0">
Toolset
{t("permissions.mcpServerPermissions.toolsetBadge")}
</span>
</div>
{toolCount > 0 && (
<div className="flex items-center gap-1 flex-shrink-0 whitespace-nowrap">
<span className="text-xs font-medium text-gray-600">{toolCount}</span>
<span className="text-xs text-gray-500">{toolCount === 1 ? "tool" : "tools"}</span>
<span className="text-xs text-gray-500">
{t("permissions.mcpServerPermissions.toolCount", { count: toolCount })}
</span>
{isExpanded ? (
<ChevronDownIcon className="h-3.5 w-3.5 text-gray-400 ml-0.5" />
) : (
@ -238,7 +247,7 @@ export function MCPServerPermissions({
) : (
<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-gray-50 border border-gray-200">
<ServerIcon className="h-4 w-4 text-gray-400" />
<Text className="text-gray-500 text-sm">No MCP servers, access groups, or toolsets configured</Text>
<Text className="text-gray-500 text-sm">{t("permissions.mcpServerPermissions.empty")}</Text>
</div>
)}
</div>

View file

@ -1,6 +1,7 @@
import React, { useState, useEffect } from "react";
import { Text, Badge } from "@tremor/react";
import { DatabaseIcon } from "@heroicons/react/outline";
import { useTranslation } from "react-i18next";
import { vectorStoreListCall } from "../networking";
interface VectorStoreDetails {
@ -14,6 +15,7 @@ interface VectorStorePermissionsProps {
}
export function VectorStorePermissions({ vectorStores, accessToken }: VectorStorePermissionsProps) {
const { t } = useTranslation();
const [vectorStoreDetails, setVectorStoreDetails] = useState<VectorStoreDetails[]>([]);
// Fetch vector store details when component mounts
@ -52,7 +54,7 @@ export function VectorStorePermissions({ vectorStores, accessToken }: VectorStor
<div className="space-y-3">
<div className="flex items-center gap-2">
<DatabaseIcon className="h-4 w-4 text-blue-600" />
<Text className="font-semibold text-gray-900">Vector Stores</Text>
<Text className="font-semibold text-gray-900">{t("permissions.vectorStorePermissions.title")}</Text>
<Badge color="blue" size="xs">
{vectorStores.length}
</Badge>
@ -72,7 +74,7 @@ export function VectorStorePermissions({ vectorStores, accessToken }: VectorStor
) : (
<div className="flex items-center gap-2 px-3 py-2 rounded-lg bg-gray-50 border border-gray-200">
<DatabaseIcon className="h-4 w-4 text-gray-400" />
<Text className="text-gray-500 text-sm">No vector stores configured</Text>
<Text className="text-gray-500 text-sm">{t("permissions.vectorStorePermissions.empty")}</Text>
</div>
)}
</div>

View file

@ -7708,5 +7708,26 @@
"testConnection": "Test Connection",
"saveChanges": "Save Changes"
}
},
"permissions": {
"agentPermissions": {
"title": "Agents",
"fullIdTooltip": "Full ID: {{id}}",
"groupBadge": "Group",
"empty": "No agents or access groups configured"
},
"mcpServerPermissions": {
"title": "MCP Servers",
"fullIdTooltip": "Full ID: {{id}}",
"groupBadge": "Group",
"toolsetBadge": "Toolset",
"toolCount_one": "tool",
"toolCount_other": "tools",
"empty": "No MCP servers, access groups, or toolsets configured"
},
"vectorStorePermissions": {
"title": "Vector Stores",
"empty": "No vector stores configured"
}
}
}

View file

@ -7708,5 +7708,26 @@
"testConnection": "测试连接",
"saveChanges": "保存更改"
}
},
"permissions": {
"agentPermissions": {
"title": "Agent",
"fullIdTooltip": "完整 ID: {{id}}",
"groupBadge": "Group",
"empty": "未配置任何 Agent 或访问组"
},
"mcpServerPermissions": {
"title": "MCP 服务器",
"fullIdTooltip": "完整 ID: {{id}}",
"groupBadge": "Group",
"toolsetBadge": "工具集",
"toolCount_one": "个工具",
"toolCount_other": "个工具",
"empty": "未配置任何 MCP 服务器、访问组或工具集"
},
"vectorStorePermissions": {
"title": "向量存储",
"empty": "未配置任何向量存储"
}
}
}