批量转换脚本引入的语法错误已回退,保留稳定的 i18n 转换: - 翻译词典: 22 namespaces, 3600+ keys - 已接入: 145+ 文件 (Dashboard/Login/K8s 主页面/Monitor/System/Deploy) - 语言切换器在 Header 中可用 (🇨🇳/🇺🇸) - tsc 零错误, Vite 构建成功
74 lines
3.0 KiB
TypeScript
74 lines
3.0 KiB
TypeScript
// YAML 导入对话框 — 粘贴/应用多文档 manifest // Logan.Li
|
|
import { useState } from 'react';
|
|
import { X, Upload, Loader2 } from 'lucide-react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { ModalOverlay } from '@/components/ui/modal-overlay';
|
|
import { useToast } from '@/hooks/use-toast';
|
|
import { kubernetesApi } from '@/api';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { YamlCodeMirror } from './YamlCodeMirror';
|
|
import type { JsonData } from '@/types/common';
|
|
|
|
interface YamlImportDialogProps {
|
|
clusterCode: string;
|
|
onClose: () => void;
|
|
onApplied?: () => void;
|
|
}
|
|
|
|
export function YamlImportDialog({ clusterCode, onClose, onApplied }: YamlImportDialogProps) {
|
|
const { t } = useTranslation();
|
|
const { toast } = useToast();
|
|
const [content, setContent] = useState('');
|
|
const [applying, setApplying] = useState(false);
|
|
|
|
const apply = async () => {
|
|
if (!content.trim()) {
|
|
toast({ title: t('k8s.yamlImport.empty'), variant: 'destructive' });
|
|
return;
|
|
}
|
|
setApplying(true);
|
|
try {
|
|
await kubernetesApi.applyYAML(clusterCode, content);
|
|
toast({ title: t('k8s.yamlImport.success'), description: t('k8s.yamlImport.successDesc') });
|
|
onApplied?.();
|
|
onClose();
|
|
} catch (e) {
|
|
toast({ title: t('k8s.yamlImport.failed'), description: (e as JsonData).message, variant: 'destructive' });
|
|
} finally { setApplying(false); }
|
|
};
|
|
|
|
return (
|
|
<ModalOverlay onClose={onClose}>
|
|
<div
|
|
className="bg-[var(--dg-bg-primary)] border border-[var(--dg-border)] rounded-xl w-[92vw] max-w-4xl h-[85vh] flex flex-col shadow-2xl"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="flex items-center justify-between p-4 border-b border-[var(--dg-border)]">
|
|
<div className="flex items-center gap-2">
|
|
<Upload className="h-5 w-5 text-[var(--dg-text-muted)]" />
|
|
<div>
|
|
<h2 className="text-lg font-bold text-[var(--dg-text-primary)]">{t('k8s.yamlImport.title')}</h2>
|
|
<p className="text-xs text-[var(--dg-text-muted)]">{t('k8s.yamlImport.hint')}</p>
|
|
</div>
|
|
</div>
|
|
<Button variant="ghost" size="icon" className="h-8 w-8" onClick={onClose}><X className="h-4 w-4" /></Button>
|
|
</div>
|
|
<div className="flex-1 min-h-0 flex flex-col overflow-hidden p-4">
|
|
<YamlCodeMirror
|
|
value={content}
|
|
fill
|
|
fontSize="12px"
|
|
onChange={setContent}
|
|
/>
|
|
</div>
|
|
<div className="flex justify-end gap-2 p-4 border-t border-[var(--dg-border)] shrink-0">
|
|
<Button variant="outline" onClick={onClose}>{t('common.cancel')}</Button>
|
|
<Button className="bg-blue-600 hover:bg-blue-700" onClick={apply} disabled={applying}>
|
|
{applying ? <Loader2 className="h-4 w-4 animate-spin mr-1" /> : <Upload className="h-4 w-4 mr-1" />}
|
|
{t('k8s.yamlImport.apply')}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</ModalOverlay>
|
|
);
|
|
} |