'use client'; import { createRuleGroup } from '@/services/admin/server'; import { Button } from '@workspace/ui/components/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@workspace/ui/components/dialog'; import { Label } from '@workspace/ui/components/label'; import { Progress } from '@workspace/ui/components/progress'; import { Textarea } from '@workspace/ui/components/textarea'; import { Icon } from '@workspace/ui/custom-components/icon'; import yaml from 'js-yaml'; import { useTranslations } from 'next-intl'; import { useRef, useState } from 'react'; import { toast } from 'sonner'; interface ImportYamlRulesProps { onImportSuccess?: () => void; } interface RuleGroup { name: string; rules: string[]; } export default function ImportYamlRules({ onImportSuccess }: ImportYamlRulesProps) { const t = useTranslations('rules'); const [open, setOpen] = useState(false); const [loading, setLoading] = useState(false); const [yamlContent, setYamlContent] = useState(''); const [importProgress, setImportProgress] = useState(0); const [importTotal, setImportTotal] = useState(0); const [analyzing, setAnalyzing] = useState(false); const fileInputRef = useRef(null); const handleFileUpload = (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; const reader = new FileReader(); reader.onload = (event) => { const content = event.target?.result as string; setYamlContent(content); setOpen(true); }; reader.readAsText(file); e.target.value = ''; }; const processRule = (rule: string): { policyGroup: string; cleanRule: string } | null => { const parts = rule.split(','); if (parts.length === 1) { return null; } let policyGroup = 'default'; let cleanRule = rule; if (parts.length >= 3) { const thirdPart = parts[2]?.trim(); if (thirdPart) { policyGroup = thirdPart; } } cleanRule = parts.slice(0, 2).join(','); return { policyGroup, cleanRule }; }; const parseRulesIntoGroups = (rules: string[]): Record => { const groups: Record = {}; for (const rule of rules) { if (!rule.trim()) continue; const result = processRule(rule); if (result === null) continue; const { policyGroup, cleanRule } = result; if (!groups[policyGroup]) { groups[policyGroup] = []; } groups[policyGroup].push(cleanRule); } return groups; }; const handleImport = async () => { if (!yamlContent) { toast.error(t('pleaseUploadFile')); return; } setLoading(true); setAnalyzing(true); try { const parsedYaml = yaml.load(yamlContent) as any; if (!parsedYaml || !parsedYaml.rules) { throw new Error(t('invalidYamlFormat')); } let allRules: string[] = []; if (Array.isArray(parsedYaml.rules)) { allRules = parsedYaml.rules.filter((rule: string) => rule.trim()); } if (allRules.length === 0) { throw new Error(t('noValidRules')); } const ruleGroups = parseRulesIntoGroups(allRules); const groups = Object.entries(ruleGroups).map(([name, rules]) => ({ name, rules, })); setImportTotal(groups.length); setAnalyzing(false); for (let i = 0; i < groups.length; i++) { const group = groups[i]; if (!group?.name || !group?.rules.length) continue; await createRuleGroup({ name: group.name, rules: group?.rules.join('\n'), enable: false, tags: [], icon: '', }); setImportProgress(i + 1); } toast.success(t('importSuccess')); setOpen(false); setYamlContent(''); setImportProgress(0); setImportTotal(0); onImportSuccess?.(); } catch (error) { console.error('Import error:', error); toast.error(error instanceof Error ? error.message : t('importFailed')); } finally { setLoading(false); setAnalyzing(false); } }; return ( <> {t('importYamlRules')} {t('importYamlDescription')}
{yamlContent && (