import React, { useState } from 'react'; import { useNavigate } from 'react-router-dom'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { useToast } from '@/hooks/useToast'; import { useKubectl, useNamespacesInfo } from '@/hooks/useKubectl'; import { useGlobalNamespace } from '@/hooks/useGlobalNamespace'; import { ArrowLeft, Code, Upload, CheckCircle, Loader2, Settings, AlertCircle, Eye, EyeOff, } from 'lucide-react'; interface ParsedJsonData { key: string; value: string; path: string; isValid: boolean; error?: string; } function ConfigMapImportJsonPage() { const navigate = useNavigate(); const { showToast } = useToast(); const { executeCommand } = useKubectl(); const { namespaces } = useNamespacesInfo(); const { selectedNamespace: globalNamespace } = useGlobalNamespace(); const [configMapName, setConfigMapName] = useState(''); const [selectedNamespace, setSelectedNamespace] = useState(() => { return globalNamespace === 'all' ? 'default' : globalNamespace; }); const [jsonContent, setJsonContent] = useState(''); const [parsedData, setParsedData] = useState([]); const [showPreview, setShowPreview] = useState(false); const [creating, setCreating] = useState(false); const [flattenMode, setFlattenMode] = useState<'dot' | 'underscore'>('dot'); const flattenObject = ( obj: any, prefix = '', separator = '.', ): Record => { const flattened: Record = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { const newKey = prefix ? `${prefix}${separator}${key}` : key; if ( obj[key] !== null && typeof obj[key] === 'object' && !Array.isArray(obj[key]) ) { Object.assign(flattened, flattenObject(obj[key], newKey, separator)); } else { flattened[newKey] = obj[key]; } } } return flattened; }; const parseJsonFile = (content: string): ParsedJsonData[] => { const data: ParsedJsonData[] = []; try { const parsed = JSON.parse(content); const separator = flattenMode === 'dot' ? '.' : '_'; const flattened = flattenObject(parsed, '', separator); for (const [key, value] of Object.entries(flattened)) { // Convert arrays and objects to JSON strings let stringValue: string; if (Array.isArray(value)) { stringValue = JSON.stringify(value); } else if (typeof value === 'object' && value !== null) { stringValue = JSON.stringify(value); } else { stringValue = String(value); } // Validate key format (should be valid ConfigMap key) if (!/^[a-zA-Z_][a-zA-Z0-9_.-]*$/.test(key)) { data.push({ key, value: stringValue, path: key, isValid: false, error: 'Nome de chave inválido para ConfigMap', }); } else { data.push({ key, value: stringValue, path: key, isValid: true, }); } } } catch (error) { data.push({ key: 'json-parse-error', value: '', path: '', isValid: false, error: `Erro ao parsear JSON: ${error instanceof Error ? error.message : 'Erro desconhecido'}`, }); } return data; }; const handleContentChange = (content: string) => { setJsonContent(content); if (content.trim()) { const parsed = parseJsonFile(content); setParsedData(parsed); } else { setParsedData([]); } }; const handleFileUpload = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file) { const reader = new FileReader(); reader.onload = (e) => { const content = e.target?.result as string; handleContentChange(content); }; reader.readAsText(file); } }; const handleFlattenModeChange = (mode: 'dot' | 'underscore') => { setFlattenMode(mode); if (jsonContent.trim()) { const parsed = parseJsonFile(jsonContent); setParsedData(parsed); } }; const validateForm = () => { if (!configMapName.trim()) { showToast({ title: 'Erro de Validação', description: 'Nome do ConfigMap é obrigatório', variant: 'destructive', }); return false; } if (!selectedNamespace) { showToast({ title: 'Erro de Validação', description: 'Namespace é obrigatório', variant: 'destructive', }); return false; } const validData = parsedData.filter((d) => d.isValid); if (validData.length === 0) { showToast({ title: 'Erro de Validação', description: 'Nenhum dado válido encontrado', variant: 'destructive', }); return false; } return true; }; const handleCreateConfigMap = async () => { if (!validateForm()) return; setCreating(true); try { const validData = parsedData.filter((d) => d.isValid); let command = `kubectl create configmap "${configMapName}" -n "${selectedNamespace}"`; validData.forEach((item) => { command += ` --from-literal="${item.key}"="${item.value}"`; }); const result = await executeCommand(command); if (result.success) { showToast({ title: 'ConfigMap Criado com Sucesso', description: `ConfigMap "${configMapName}" foi criado com ${validData.length} chaves`, variant: 'success', }); navigate('/storage/configmaps'); } else { showToast({ title: 'Erro ao Criar ConfigMap', description: result.error || 'Falha ao criar o ConfigMap', variant: 'destructive', }); } } catch (error) { const errorMsg = error instanceof Error ? error.message : 'Erro inesperado'; showToast({ title: 'Erro', description: errorMsg, variant: 'destructive', }); } finally { setCreating(false); } }; const validData = parsedData.filter((d) => d.isValid); const invalidData = parsedData.filter((d) => !d.isValid); return (
{/* Header */}

Importar Arquivo JSON

Importe configurações de um arquivo JSON

{/* Basic Info */} Informações Básicas
setConfigMapName(e.target.value)} />
{/* File Upload */} Arquivo JSON