Refactor: Implement clipboard paste for signatures
Implement direct clipboard paste functionality for signature ingestion, removing the need for a text box and submit button.
This commit is contained in:
@@ -1,31 +1,163 @@
|
||||
|
||||
import { useParams, useNavigate } from "react-router-dom";
|
||||
import { useEffect } from "react";
|
||||
import { toast } from "@/hooks/use-toast";
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import SystemTracker from "@/components/SystemTracker";
|
||||
import SignatureIngest from "@/components/SignatureIngest";
|
||||
import RegionMap from "@/components/RegionMap";
|
||||
|
||||
interface Signature {
|
||||
identifier: string;
|
||||
type: string;
|
||||
signame: string;
|
||||
system: string;
|
||||
sysid: string;
|
||||
dangerous?: boolean;
|
||||
}
|
||||
|
||||
const SystemView = () => {
|
||||
const { system, region } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
if (!system) {
|
||||
navigate("/");
|
||||
return null;
|
||||
}
|
||||
|
||||
const parseSignature = (text: string): Omit<Signature, 'system' | 'sysid'> | null => {
|
||||
const parts = text.split('\t');
|
||||
if (parts.length < 4) return null;
|
||||
|
||||
return {
|
||||
identifier: parts[0],
|
||||
type: parts[2],
|
||||
signame: parts[3],
|
||||
dangerous: false // TODO: Implement dangerous signature detection
|
||||
};
|
||||
};
|
||||
|
||||
const getSystemId = async (systemName: string): Promise<string> => {
|
||||
const url = `https://evebase.site.quack-lab.dev/api/collections/regionview/records?filter=(sysname='${encodeURIComponent(systemName)}')`;
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
|
||||
if (data.items && data.items.length > 0) {
|
||||
return data.items[0].id;
|
||||
}
|
||||
throw new Error(`System ${systemName} not found`);
|
||||
};
|
||||
|
||||
const saveSignature = async (signature: Signature): Promise<void> => {
|
||||
// Check if signature already exists
|
||||
const existingUrl = `https://evebase.site.quack-lab.dev/api/collections/sigview/records?filter=(identifier='${signature.identifier}' && system='${signature.system}')`;
|
||||
const existingResponse = await fetch(existingUrl);
|
||||
const existingData = await existingResponse.json();
|
||||
|
||||
if (existingData.items && existingData.items.length > 0) {
|
||||
// Update existing signature
|
||||
const existingId = existingData.items[0].id;
|
||||
const updateUrl = `https://evebase.site.quack-lab.dev/api/collections/sigview/records/${existingId}`;
|
||||
const updateResponse = await fetch(updateUrl, {
|
||||
method: 'PATCH',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
signame: signature.signame,
|
||||
type: signature.type,
|
||||
dangerous: signature.dangerous
|
||||
})
|
||||
});
|
||||
|
||||
if (!updateResponse.ok) {
|
||||
throw new Error(`Failed to update signature: ${updateResponse.status}`);
|
||||
}
|
||||
} else {
|
||||
// Create new signature
|
||||
const createUrl = 'https://evebase.site.quack-lab.dev/api/collections/sigview/records';
|
||||
const createResponse = await fetch(createUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify(signature)
|
||||
});
|
||||
|
||||
if (!createResponse.ok) {
|
||||
throw new Error(`Failed to create signature: ${createResponse.status}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handlePaste = async (e: ClipboardEvent) => {
|
||||
const pastedText = e.clipboardData?.getData('text');
|
||||
if (!pastedText?.trim()) return;
|
||||
|
||||
try {
|
||||
const systemId = await getSystemId(system);
|
||||
const lines = pastedText.trim().split('\n').filter(line => line.trim());
|
||||
const parsedSignatures: Signature[] = [];
|
||||
|
||||
// Parse all signatures
|
||||
for (const line of lines) {
|
||||
const parsed = parseSignature(line);
|
||||
if (parsed) {
|
||||
parsedSignatures.push({
|
||||
...parsed,
|
||||
system,
|
||||
sysid: systemId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedSignatures.length === 0) {
|
||||
toast({
|
||||
title: "No Valid Signatures",
|
||||
description: "No valid signatures found in the pasted data.",
|
||||
variant: "destructive"
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Save all new/updated signatures
|
||||
for (const signature of parsedSignatures) {
|
||||
await saveSignature(signature);
|
||||
}
|
||||
|
||||
// Invalidate queries to refresh the data
|
||||
queryClient.invalidateQueries({ queryKey: ['signatures', system] });
|
||||
|
||||
toast({
|
||||
title: "Success",
|
||||
description: `${parsedSignatures.length} signatures processed.`
|
||||
});
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to process signatures:', error);
|
||||
toast({
|
||||
title: "Error",
|
||||
description: error instanceof Error ? error.message : "Failed to process signatures.",
|
||||
variant: "destructive"
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
document.addEventListener('paste', handlePaste);
|
||||
return () => {
|
||||
document.removeEventListener('paste', handlePaste);
|
||||
};
|
||||
}, [system]);
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900">
|
||||
<div className="container mx-auto px-4 py-8">
|
||||
<div className="text-center mb-8">
|
||||
<h1 className="text-4xl font-bold text-white mb-2">System: {system}</h1>
|
||||
<p className="text-slate-300">Viewing signatures and regional overview</p>
|
||||
<p className="text-slate-300">Viewing signatures and regional overview • Press Ctrl+V to paste signatures</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
{/* Main content - signatures and ingestion */}
|
||||
{/* Main content - signatures */}
|
||||
<div className="lg:col-span-2 space-y-6">
|
||||
<SystemTracker system={system} />
|
||||
<SignatureIngest system={system} region={region || ''} />
|
||||
</div>
|
||||
|
||||
{/* Regional overview map */}
|
||||
|
||||
Reference in New Issue
Block a user