121 lines
3.6 KiB
TypeScript
121 lines
3.6 KiB
TypeScript
import { useRef } from 'react';
|
|
import { Upload, Download, FilePlus, File } from 'lucide-react';
|
|
import { Button } from '../components/ui';
|
|
import { Config } from '../models/Config';
|
|
import { ConfigReader } from '../models/ConfigReader';
|
|
import { ConfigBuilder } from '../builders/ConfigBuilder';
|
|
import { Env } from '../models/Env';
|
|
|
|
interface FileChooserProps {
|
|
onSelected: (config: Config) => void;
|
|
config?: Config;
|
|
}
|
|
|
|
export function FileChooser({ onSelected, config }: FileChooserProps) {
|
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
|
|
|
async function handleFileChange(event: React.ChangeEvent<HTMLInputElement>) {
|
|
const file = event.target.files?.[0];
|
|
if (!file) return;
|
|
|
|
console.log(file.name, file.type, file.size, 'supported:', ConfigReader.isSupportedFormat(file));
|
|
|
|
const reader = new ConfigReader();
|
|
const cfg = await reader.parseFromFile(file);
|
|
|
|
if (cfg !== null) {
|
|
onSelected(cfg);
|
|
}
|
|
|
|
// Reset input
|
|
if (fileInputRef.current) {
|
|
fileInputRef.current.value = '';
|
|
}
|
|
}
|
|
|
|
function handleNew() {
|
|
const cfg = new Config();
|
|
cfg.setEnvs([new Env(0, 'DEFAULT', [])]);
|
|
cfg.setTemplate('{}');
|
|
onSelected(cfg);
|
|
}
|
|
|
|
function handleDownload() {
|
|
if (!config) {
|
|
alert('No configuration loaded');
|
|
return;
|
|
}
|
|
|
|
const xmlContent = ConfigBuilder.buildFullXml(config);
|
|
const filename = ConfigBuilder.generateFilename();
|
|
|
|
const blob = new Blob([xmlContent], { type: 'text/xml' });
|
|
const url = URL.createObjectURL(blob);
|
|
const link = document.createElement('a');
|
|
link.href = url;
|
|
link.download = filename;
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
URL.revokeObjectURL(url);
|
|
}
|
|
|
|
return (
|
|
<div className="bg-white rounded-xl shadow-md p-4 border border-slate-200">
|
|
<div className="flex items-center gap-4 flex-wrap">
|
|
{/* Logo/Brand */}
|
|
<div className="flex items-center gap-2">
|
|
<div className="w-10 h-10 bg-gradient-to-br from-blue-500 to-blue-600 rounded-lg flex items-center justify-center">
|
|
<File className="w-6 h-6 text-white" />
|
|
</div>
|
|
<span className="font-bold text-xl text-slate-800">Configucci</span>
|
|
</div>
|
|
|
|
<div className="h-8 w-px bg-slate-200" />
|
|
|
|
{/* Action Buttons */}
|
|
<div className="flex items-center gap-2 flex-1">
|
|
<Button
|
|
variant="primary"
|
|
onClick={handleNew}
|
|
icon={FilePlus}
|
|
size="sm"
|
|
>
|
|
New Config
|
|
</Button>
|
|
|
|
<Button
|
|
variant="success"
|
|
onClick={handleDownload}
|
|
icon={Download}
|
|
size="sm"
|
|
disabled={!config}
|
|
title="Download full config template"
|
|
>
|
|
Download
|
|
</Button>
|
|
|
|
<span className="text-slate-400 text-sm">or</span>
|
|
|
|
{/* File Upload */}
|
|
<div className="flex-1">
|
|
<label
|
|
className="flex items-center justify-center gap-2 px-4 py-2 border-2 border-dashed border-slate-300 rounded-lg cursor-pointer hover:border-blue-400 hover:bg-blue-50 transition-all duration-200"
|
|
>
|
|
<Upload className="w-4 h-4 text-slate-400" />
|
|
<span className="text-sm text-slate-600">Upload XML Config</span>
|
|
<input
|
|
ref={fileInputRef}
|
|
type="file"
|
|
className="hidden"
|
|
accept=".xml,text/xml"
|
|
onChange={handleFileChange}
|
|
/>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|