feat(mcp): show inline duplicate ID error and block submit in add mode
- Display red hint next to title when ID exists - Disable Add/Save button and prevent submit on duplicate - Accept existing IDs via prop for real-time validation - Remove overwrite confirmation dialog on add - i18n: add duplicate-ID error strings and remove unused overwrite prompt - files: - src/components/mcp/McpFormModal.tsx - src/components/mcp/McpPanel.tsx - src/i18n/locales/en.json - src/i18n/locales/zh.json
This commit is contained in:
@@ -11,6 +11,7 @@ interface McpFormModalProps {
|
||||
initialData?: McpServer;
|
||||
onSave: (id: string, server: McpServer) => Promise<void>;
|
||||
onClose: () => void;
|
||||
existingIds?: string[];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,6 +39,7 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
|
||||
initialData,
|
||||
onSave,
|
||||
onClose,
|
||||
existingIds = [],
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [formId, setFormId] = useState(editingId || "");
|
||||
@@ -50,10 +52,19 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
|
||||
const [jsonError, setJsonError] = useState("");
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [isWizardOpen, setIsWizardOpen] = useState(false);
|
||||
const [idError, setIdError] = useState("");
|
||||
|
||||
// 编辑模式下禁止修改 ID
|
||||
const isEditing = !!editingId;
|
||||
|
||||
const handleIdChange = (value: string) => {
|
||||
setFormId(value);
|
||||
if (!isEditing) {
|
||||
const exists = existingIds.includes(value.trim());
|
||||
setIdError(exists ? t("mcp.error.idExists") : "");
|
||||
}
|
||||
};
|
||||
|
||||
const handleJsonChange = (value: string) => {
|
||||
setFormJson(value);
|
||||
|
||||
@@ -104,6 +115,12 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
|
||||
return;
|
||||
}
|
||||
|
||||
// 新增模式:阻止提交重名 ID
|
||||
if (!isEditing && existingIds.includes(formId.trim())) {
|
||||
setIdError(t("mcp.error.idExists"));
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证 JSON
|
||||
const currentJsonError = validateJson(formJson);
|
||||
setJsonError(currentJsonError);
|
||||
@@ -186,14 +203,21 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
|
||||
<div className="p-6 space-y-4">
|
||||
{/* ID (标题) */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-2">
|
||||
<div className="flex items-center justify-between mb-2">
|
||||
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
|
||||
{t("mcp.form.title")} <span className="text-red-500">*</span>
|
||||
</label>
|
||||
{!isEditing && idError && (
|
||||
<span className="text-xs text-red-500 dark:text-red-400">
|
||||
{idError}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<input
|
||||
className={inputStyles.text}
|
||||
placeholder={t("mcp.form.titlePlaceholder")}
|
||||
value={formId}
|
||||
onChange={(e) => setFormId(e.target.value)}
|
||||
onChange={(e) => handleIdChange(e.target.value)}
|
||||
disabled={isEditing}
|
||||
/>
|
||||
</div>
|
||||
@@ -247,7 +271,7 @@ const McpFormModal: React.FC<McpFormModalProps> = ({
|
||||
</button>
|
||||
<button
|
||||
onClick={handleSubmit}
|
||||
disabled={saving}
|
||||
disabled={saving || (!isEditing && !!idError)}
|
||||
className={buttonStyles.primary}
|
||||
>
|
||||
<Save size={16} />
|
||||
|
||||
@@ -292,6 +292,7 @@ const McpPanel: React.FC<McpPanelProps> = ({ onClose, onNotify }) => {
|
||||
<McpFormModal
|
||||
editingId={editingId || undefined}
|
||||
initialData={editingId ? servers[editingId] : undefined}
|
||||
existingIds={Object.keys(servers)}
|
||||
onSave={handleSave}
|
||||
onClose={handleCloseForm}
|
||||
/>
|
||||
|
||||
@@ -316,6 +316,7 @@
|
||||
},
|
||||
"error": {
|
||||
"idRequired": "Please enter identifier",
|
||||
"idExists": "Identifier already exists. Please choose another.",
|
||||
"jsonInvalid": "Invalid JSON format",
|
||||
"commandRequired": "Please enter command",
|
||||
"singleServerObjectRequired": "Please paste a single MCP server object (do not include top-level mcpServers)",
|
||||
|
||||
@@ -316,6 +316,7 @@
|
||||
},
|
||||
"error": {
|
||||
"idRequired": "请填写标识",
|
||||
"idExists": "该标识已存在,请更换",
|
||||
"jsonInvalid": "JSON 格式错误,请检查",
|
||||
"commandRequired": "请填写命令",
|
||||
"singleServerObjectRequired": "此处只需单个服务器对象,请不要粘贴包含 mcpServers 的整份配置",
|
||||
|
||||
Reference in New Issue
Block a user