Implement manually editing signatures

This commit is contained in:
2025-06-22 17:13:46 +02:00
parent 6bc13eb55f
commit 890b77ec2d
7 changed files with 507 additions and 158 deletions

View File

@@ -1,3 +1,4 @@
import { useState } from "react";
import { Card, CardContent } from "@/components/ui/card"; import { Card, CardContent } from "@/components/ui/card";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
@@ -15,13 +16,16 @@ import {
import { SigviewRecord as Signature } from "@/lib/pbtypes"; import { SigviewRecord as Signature } from "@/lib/pbtypes";
import { getSignatureMeta } from "@/hooks/useSignatureCategories"; import { getSignatureMeta } from "@/hooks/useSignatureCategories";
import { Trash2 } from "lucide-react"; import { Trash2 } from "lucide-react";
import { SignatureEditModal } from "@/components/SignatureEditModal";
interface SignatureCardProps { interface SignatureCardProps {
signature: Signature; signature: Signature;
onDelete?: (signatureId: string) => Promise<void>; onDelete?: (signatureId: string) => Promise<void>;
onUpdate?: (updatedSignature: Partial<Signature>) => Promise<void>;
} }
export const SignatureCard = ({ signature, onDelete }: SignatureCardProps) => { export const SignatureCard = ({ signature, onDelete, onUpdate }: SignatureCardProps) => {
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const meta = getSignatureMeta(signature.type); const meta = getSignatureMeta(signature.type);
const isGasSite = signature.type?.toLowerCase().includes('gas'); const isGasSite = signature.type?.toLowerCase().includes('gas');
@@ -35,79 +39,106 @@ export const SignatureCard = ({ signature, onDelete }: SignatureCardProps) => {
} }
}; };
return ( const handleUpdate = async (updatedSignature: Partial<Signature>) => {
<Card className={`${isGasSite ? 'bg-emerald-900/40 border-emerald-500 shadow-[0_0_15px_rgba(16,185,129,0.5)] hover:shadow-[0_0_20px_rgba(16,185,129,0.7)]' : 'bg-slate-800/40 border-slate-700'} hover:bg-slate-800/60 transition-all duration-200 hover:border-slate-600 relative`}> if (onUpdate) {
<CardContent className="pt-6"> try {
<div className="space-y-3"> await onUpdate(updatedSignature);
{/* Type Badge - Most Important */} } catch (error) {
<div className="flex items-center justify-center"> console.error('Failed to update signature:', error);
<Badge throw error;
variant="outline" }
className={`${meta.color} px-3 py-1 text-sm font-semibold flex items-center gap-2`} }
> };
{meta.icon}
{signature.type || 'Unknown Type'}
</Badge>
</div>
{/* Signature Name */}
<div className="text-center">
<h3 className="text-white font-medium text-lg">
{signature.signame || 'Unnamed Signature'}
</h3>
</div>
{/* Additional Info */}
<div className="space-y-2 text-sm text-slate-400">
<div className="flex justify-between">
<span>System:</span>
<span className="text-slate-200">{signature.system}</span>
</div>
<div className="flex justify-between">
<span>ID:</span>
<span className="text-slate-200 font-mono text-xs">{signature.id}</span>
</div>
</div>
</div>
{/* Delete Button */} return (
{onDelete && ( <>
<div className="absolute top-2 right-2"> <Card
<AlertDialog> className={`${isGasSite ? 'bg-emerald-900/40 border-emerald-500 shadow-[0_0_15px_rgba(16,185,129,0.5)] hover:shadow-[0_0_20px_rgba(16,185,129,0.7)]' : 'bg-slate-800/40 border-slate-700'} hover:bg-slate-800/60 transition-all duration-200 hover:border-slate-600 relative cursor-pointer`}
<AlertDialogTrigger asChild> onClick={() => setIsEditModalOpen(true)}
<Button >
variant="ghost" <CardContent className="pt-6">
size="icon" <div className="space-y-3">
className="h-6 w-6 text-slate-400 hover:text-red-400 hover:bg-red-900/20 transition-colors" {/* Type Badge - Most Important */}
> <div className="flex items-center justify-center">
<Trash2 className="h-3 w-3" /> <Badge
</Button> variant="outline"
</AlertDialogTrigger> className={`${meta.color} px-3 py-1 text-sm font-semibold flex items-center gap-2`}
<AlertDialogContent className="bg-slate-800 border-slate-700"> >
<AlertDialogHeader> {meta.icon}
<AlertDialogTitle className="text-white">Delete Signature</AlertDialogTitle> {signature.type || 'Unknown Type'}
<AlertDialogDescription className="text-slate-300"> </Badge>
Are you sure you want to delete signature <span className="font-mono text-white">{signature.identifier}</span>? </div>
<br />
This action cannot be undone. {/* Signature Name */}
</AlertDialogDescription> <div className="text-center">
</AlertDialogHeader> <h3 className="text-white font-medium text-lg">
<AlertDialogFooter> {signature.signame || 'Unnamed Signature'}
<AlertDialogCancel className="bg-slate-700 border-slate-600 text-slate-200 hover:bg-slate-600"> </h3>
Cancel </div>
</AlertDialogCancel>
<AlertDialogAction {/* Additional Info */}
onClick={handleDelete} <div className="space-y-2 text-sm text-slate-400">
className="bg-red-600 hover:bg-red-700 text-white" <div className="flex justify-between">
> <span>System:</span>
Delete <span className="text-slate-200">{signature.system}</span>
</AlertDialogAction> </div>
</AlertDialogFooter> <div className="flex justify-between">
</AlertDialogContent> <span>ID:</span>
</AlertDialog> <span className="text-slate-200 font-mono text-xs">{signature.id}</span>
</div>
</div>
</div> </div>
)}
</CardContent> {/* Delete Button */}
</Card> {onDelete && (
<div className="absolute top-2 right-2">
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
variant="ghost"
size="icon"
className="h-6 w-6 text-slate-400 hover:text-red-400 hover:bg-red-900/20 transition-colors"
onClick={(e) => e.stopPropagation()} // Prevent opening edit modal when clicking delete
>
<Trash2 className="h-3 w-3" />
</Button>
</AlertDialogTrigger>
<AlertDialogContent className="bg-slate-800 border-slate-700">
<AlertDialogHeader>
<AlertDialogTitle className="text-white">Delete Signature</AlertDialogTitle>
<AlertDialogDescription className="text-slate-300">
Are you sure you want to delete signature <span className="font-mono text-white">{signature.identifier}</span>?
<br />
This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel className="bg-slate-700 border-slate-600 text-slate-200 hover:bg-slate-600">
Cancel
</AlertDialogCancel>
<AlertDialogAction
onClick={handleDelete}
className="bg-red-600 hover:bg-red-700 text-white"
>
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</div>
)}
</CardContent>
</Card>
{/* Edit Modal */}
{onUpdate && (
<SignatureEditModal
signature={signature}
isOpen={isEditModalOpen}
onClose={() => setIsEditModalOpen(false)}
onSave={handleUpdate}
/>
)}
</>
); );
}; };

View File

@@ -4,14 +4,16 @@ import { Collapsible, CollapsibleContent, CollapsibleTrigger } from "@/component
import { ChevronDown, ChevronRight } from "lucide-react"; import { ChevronDown, ChevronRight } from "lucide-react";
import { SignatureListItem } from "@/components/SignatureListItem"; import { SignatureListItem } from "@/components/SignatureListItem";
import { SignatureCategory } from "@/hooks/useSignatureCategories"; import { SignatureCategory } from "@/hooks/useSignatureCategories";
import { SigviewRecord as Signature } from "@/lib/pbtypes";
interface SignatureCategoriesProps { interface SignatureCategoriesProps {
categories: SignatureCategory[]; categories: SignatureCategory[];
onToggleCategory: (categoryId: string) => void; onToggleCategory: (categoryId: string) => void;
onDelete?: (signatureId: string) => Promise<void>; onDelete?: (signatureId: string) => Promise<void>;
onUpdate?: (updatedSignature: Partial<Signature>) => Promise<void>;
} }
export const SignatureCategories = ({ categories, onToggleCategory, onDelete }: SignatureCategoriesProps) => { export const SignatureCategories = ({ categories, onToggleCategory, onDelete, onUpdate }: SignatureCategoriesProps) => {
if (categories.length === 0) { if (categories.length === 0) {
return ( return (
<Card className="bg-slate-800/30 border-slate-700"> <Card className="bg-slate-800/30 border-slate-700">
@@ -51,7 +53,12 @@ export const SignatureCategories = ({ categories, onToggleCategory, onDelete }:
<CardContent className="p-0"> <CardContent className="p-0">
<div className="divide-y divide-slate-700"> <div className="divide-y divide-slate-700">
{category.signatures.map((signature) => ( {category.signatures.map((signature) => (
<SignatureListItem key={signature.id} signature={signature} onDelete={onDelete} /> <SignatureListItem
key={signature.id}
signature={signature}
onDelete={onDelete}
onUpdate={onUpdate}
/>
))} ))}
</div> </div>
</CardContent> </CardContent>

View File

@@ -0,0 +1,208 @@
import { useState } from "react";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Switch } from "@/components/ui/switch";
import { Badge } from "@/components/ui/badge";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { SigviewRecord as Signature } from "@/lib/pbtypes";
import { getSignatureMeta, getSignatureTypes } from "@/hooks/useSignatureCategories";
import { toast } from "@/hooks/use-toast";
interface SignatureEditModalProps {
signature: Signature;
isOpen: boolean;
onClose: () => void;
onSave: (updatedSignature: Partial<Signature>) => Promise<void>;
}
export const SignatureEditModal = ({ signature, isOpen, onClose, onSave }: SignatureEditModalProps) => {
const [formData, setFormData] = useState({
type: signature.type || "unknown",
signame: signature.signame || "",
dangerous: signature.dangerous || false,
scanned: signature.scanned || "",
identifier: signature.identifier || ""
});
const [isLoading, setIsLoading] = useState(false);
const signatureTypes = getSignatureTypes();
const currentMeta = getSignatureMeta(formData.type === "unknown" ? "" : formData.type);
const handleSave = async () => {
setIsLoading(true);
try {
await onSave({
identifier: signature.identifier,
type: formData.type === "unknown" ? undefined : formData.type,
signame: formData.signame || undefined,
dangerous: formData.dangerous,
scanned: formData.scanned || undefined
});
onClose();
toast({
title: "Signature Updated",
description: "The signature has been successfully updated.",
});
} catch (error) {
console.error('Failed to update signature:', error);
toast({
title: "Update Failed",
description: error instanceof Error ? error.message : "Failed to update signature.",
variant: "destructive"
});
} finally {
setIsLoading(false);
}
};
const handleClose = () => {
// Reset form data to original values when closing
setFormData({
type: signature.type || "unknown",
signame: signature.signame || "",
dangerous: signature.dangerous || false,
scanned: signature.scanned || "",
identifier: signature.identifier || ""
});
onClose();
};
return (
<Dialog open={isOpen} onOpenChange={handleClose}>
<DialogContent className="bg-slate-800 border-slate-700 max-w-md">
<DialogHeader>
<DialogTitle className="text-white flex items-center gap-2">
{currentMeta.icon}
Edit Signature
</DialogTitle>
<DialogDescription className="text-slate-300">
Modify the signature details below. All changes will be saved immediately.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
{/* Signature Identifier (Read-only) */}
<div className="space-y-2">
<Label htmlFor="identifier" className="text-slate-200">Signature ID</Label>
<Input
id="identifier"
value={formData.identifier}
disabled
className="bg-slate-700 border-slate-600 text-slate-300 font-mono"
/>
</div>
{/* Signature Type */}
<div className="space-y-2">
<Label htmlFor="type" className="text-slate-200">Type</Label>
<Select value={formData.type} onValueChange={(value) => setFormData(prev => ({ ...prev, type: value }))}>
<SelectTrigger className="bg-slate-700 border-slate-600 text-slate-200">
<SelectValue placeholder="Select signature type" />
</SelectTrigger>
<SelectContent className="bg-slate-700 border-slate-600">
<SelectItem value="unknown" className="text-slate-200">Unknown Type</SelectItem>
{signatureTypes.map((type) => (
<SelectItem key={type} value={type} className="text-slate-200">
{type}
</SelectItem>
))}
</SelectContent>
</Select>
{formData.type !== "unknown" && (
<Badge variant="outline" className={`${currentMeta.color} mt-2`}>
{currentMeta.icon}
{formData.type}
</Badge>
)}
</div>
{/* Signature Name */}
<div className="space-y-2">
<Label htmlFor="signame" className="text-slate-200">Name</Label>
<Input
id="signame"
value={formData.signame}
onChange={(e) => setFormData(prev => ({ ...prev, signame: e.target.value }))}
placeholder="Enter signature name"
className="bg-slate-700 border-slate-600 text-slate-200"
/>
</div>
{/* Scanned Percentage */}
<div className="space-y-2">
<Label htmlFor="scanned" className="text-slate-200">Scanned (%)</Label>
<Input
id="scanned"
type="number"
min="0"
max="100"
value={formData.scanned}
onChange={(e) => setFormData(prev => ({ ...prev, scanned: e.target.value }))}
placeholder="0-100"
className="bg-slate-700 border-slate-600 text-slate-200"
/>
</div>
{/* Dangerous Flag */}
<div className="flex items-center justify-between">
<Label htmlFor="dangerous" className="text-slate-200">Dangerous</Label>
<Switch
id="dangerous"
checked={formData.dangerous}
onCheckedChange={(checked) => setFormData(prev => ({ ...prev, dangerous: checked }))}
/>
</div>
{/* Preview */}
<div className="pt-4 border-t border-slate-600">
<Label className="text-slate-200 text-sm">Preview</Label>
<div className="mt-2 p-3 bg-slate-700 rounded border border-slate-600">
<div className="flex items-center gap-2 mb-2">
<Badge variant="outline" className={`${currentMeta.color}`}>
{currentMeta.icon}
{formData.type === "unknown" ? "Unknown Type" : formData.type}
</Badge>
{formData.dangerous && (
<Badge variant="outline" className="bg-red-900/50 text-red-200 border-red-500">
DANGEROUS
</Badge>
)}
</div>
<div className="text-slate-200 font-mono text-sm">{formData.identifier}</div>
<div className="text-white">{formData.signame || "Unnamed Signature"}</div>
{formData.scanned && (
<div className="text-slate-400 text-sm">Scanned: {formData.scanned}%</div>
)}
</div>
</div>
</div>
<DialogFooter>
<Button
variant="outline"
onClick={handleClose}
className="bg-slate-700 border-slate-600 text-slate-200 hover:bg-slate-600"
>
Cancel
</Button>
<Button
onClick={handleSave}
disabled={isLoading}
className="bg-blue-600 hover:bg-blue-700 text-white"
>
{isLoading ? "Saving..." : "Save Changes"}
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};

View File

@@ -1,3 +1,4 @@
import { useState } from "react";
import { Badge } from "@/components/ui/badge"; import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { import {
@@ -14,13 +15,17 @@ import {
import { Clock, AlertTriangle, Skull, Trash2 } from "lucide-react"; import { Clock, AlertTriangle, Skull, Trash2 } from "lucide-react";
import { SigviewRecord as Signature } from "@/lib/pbtypes"; import { SigviewRecord as Signature } from "@/lib/pbtypes";
import { getSignatureMeta } from "@/hooks/useSignatureCategories"; import { getSignatureMeta } from "@/hooks/useSignatureCategories";
import { SignatureEditModal } from "@/components/SignatureEditModal";
interface SignatureListItemProps { interface SignatureListItemProps {
signature: Signature; signature: Signature;
onDelete?: (signatureId: string) => Promise<void>; onDelete?: (signatureId: string) => Promise<void>;
onUpdate?: (updatedSignature: Partial<Signature>) => Promise<void>;
} }
export const SignatureListItem = ({ signature, onDelete }: SignatureListItemProps) => { export const SignatureListItem = ({ signature, onDelete, onUpdate }: SignatureListItemProps) => {
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
const isOld = () => { const isOld = () => {
if (!signature.updated) return false; if (!signature.updated) return false;
const updatedTime = new Date(signature.updated); const updatedTime = new Date(signature.updated);
@@ -69,91 +74,116 @@ export const SignatureListItem = ({ signature, onDelete }: SignatureListItemProp
} }
}; };
return ( const handleUpdate = async (updatedSignature: Partial<Signature>) => {
<div if (onUpdate) {
className={`flex items-center justify-between p-4 border-b border-slate-700 hover:bg-slate-800/40 transition-colors ${ try {
oldEntry ? "opacity-50" : "" await onUpdate(updatedSignature);
} ${isGasSite ? 'bg-emerald-900/40 border-emerald-500 shadow-[0_0_15px_rgba(16,185,129,0.5)] hover:shadow-[0_0_20px_rgba(16,185,129,0.7)]' : ''}`} } catch (error) {
> console.error('Failed to update signature:', error);
<div className="flex items-center gap-4 flex-1"> throw error;
{/* Type Badge - Most Important */} }
<Badge }
variant="outline" };
className={`${meta.color} px-3 py-1 text-sm font-semibold flex items-center gap-2 min-w-[120px] justify-center`}
>
{signature.dangerous
? <Skull className="h-4 w-4 text-red-400 animate-pulse" />
: meta.icon}
{signature.type || "Unknown Type"}
</Badge>
{/* Signature Name and ID */} return (
<div className="flex-1 min-w-[200px]"> <>
<div className="flex items-center gap-2"> <div
<span className="font-mono text-sm text-slate-400 min-w-[60px]">{signature.identifier}</span> className={`flex items-center justify-between p-4 border-b border-slate-700 hover:bg-slate-800/40 transition-colors cursor-pointer ${
<h3 className="text-white font-medium flex items-center gap-2"> oldEntry ? "opacity-50" : ""
{signature.signame || "Unnamed Signature"} } ${isGasSite ? 'bg-emerald-900/40 border-emerald-500 shadow-[0_0_15px_rgba(16,185,129,0.5)] hover:shadow-[0_0_20px_rgba(16,185,129,0.7)]' : ''}`}
{signature.dangerous && ( onClick={() => setIsEditModalOpen(true)}
<Badge variant="outline" className="bg-red-900/50 text-red-200 border-red-500 px-2 py-0.5 text-xs"> >
DANGEROUS <div className="flex items-center gap-4 flex-1">
</Badge> {/* Type Badge - Most Important */}
)} <Badge
</h3> variant="outline"
className={`${meta.color} px-3 py-1 text-sm font-semibold flex items-center gap-2 min-w-[120px] justify-center`}
>
{signature.dangerous
? <Skull className="h-4 w-4 text-red-400 animate-pulse" />
: meta.icon}
{signature.type || "Unknown Type"}
</Badge>
{/* Signature Name and ID */}
<div className="flex-1 min-w-[200px]">
<div className="flex items-center gap-2">
<span className="font-mono text-sm text-slate-400 min-w-[60px]">{signature.identifier}</span>
<h3 className="text-white font-medium flex items-center gap-2">
{signature.signame || "Unnamed Signature"}
{signature.dangerous && (
<Badge variant="outline" className="bg-red-900/50 text-red-200 border-red-500 px-2 py-0.5 text-xs">
DANGEROUS
</Badge>
)}
</h3>
</div>
</div>
{/* Dates */}
<div className="flex flex-col gap-1 text-sm text-slate-400 min-w-[200px]">
{signature.updated && (
<div className="flex items-center gap-2">
{oldEntry && <AlertTriangle className="h-4 w-4 text-yellow-500" />}
<Clock className="h-4 w-4" />
<span>Updated: {formatDate(signature.updated)}</span>
</div>
)}
{signature.created && (
<div className="flex items-center gap-2 text-xs text-slate-500">
<span>Created: {formatDate(signature.created)}</span>
</div>
)}
</div> </div>
</div> </div>
{/* Dates */} {/* Delete Button */}
<div className="flex flex-col gap-1 text-sm text-slate-400 min-w-[200px]"> {onDelete && (
{signature.updated && ( <AlertDialog>
<div className="flex items-center gap-2"> <AlertDialogTrigger asChild>
{oldEntry && <AlertTriangle className="h-4 w-4 text-yellow-500" />} <Button
<Clock className="h-4 w-4" /> variant="ghost"
<span>Updated: {formatDate(signature.updated)}</span> size="icon"
</div> className="h-8 w-8 text-slate-400 hover:text-red-400 hover:bg-red-900/20 transition-colors"
)} onClick={(e) => e.stopPropagation()} // Prevent opening edit modal when clicking delete
{signature.created && ( >
<div className="flex items-center gap-2 text-xs text-slate-500"> <Trash2 className="h-4 w-4" />
<span>Created: {formatDate(signature.created)}</span> </Button>
</div> </AlertDialogTrigger>
)} <AlertDialogContent className="bg-slate-800 border-slate-700">
</div> <AlertDialogHeader>
<AlertDialogTitle className="text-white">Delete Signature</AlertDialogTitle>
<AlertDialogDescription className="text-slate-300">
Are you sure you want to delete signature <span className="font-mono text-white">{signature.identifier}</span>?
<br />
This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel className="bg-slate-700 border-slate-600 text-slate-200 hover:bg-slate-600">
Cancel
</AlertDialogCancel>
<AlertDialogAction
onClick={handleDelete}
className="bg-red-600 hover:bg-red-700 text-white"
>
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)}
</div> </div>
{/* Delete Button */} {/* Edit Modal */}
{onDelete && ( {onUpdate && (
<AlertDialog> <SignatureEditModal
<AlertDialogTrigger asChild> signature={signature}
<Button isOpen={isEditModalOpen}
variant="ghost" onClose={() => setIsEditModalOpen(false)}
size="icon" onSave={handleUpdate}
className="h-8 w-8 text-slate-400 hover:text-red-400 hover:bg-red-900/20 transition-colors" />
>
<Trash2 className="h-4 w-4" />
</Button>
</AlertDialogTrigger>
<AlertDialogContent className="bg-slate-800 border-slate-700">
<AlertDialogHeader>
<AlertDialogTitle className="text-white">Delete Signature</AlertDialogTitle>
<AlertDialogDescription className="text-slate-300">
Are you sure you want to delete signature <span className="font-mono text-white">{signature.identifier}</span>?
<br />
This action cannot be undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel className="bg-slate-700 border-slate-600 text-slate-200 hover:bg-slate-600">
Cancel
</AlertDialogCancel>
<AlertDialogAction
onClick={handleDelete}
className="bg-red-600 hover:bg-red-700 text-white"
>
Delete
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)} )}
</div> </>
); );
}; };

View File

@@ -4,21 +4,21 @@ import { Badge } from "@/components/ui/badge";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { RefreshCw, AlertCircle, Radar, Download } from "lucide-react"; import { RefreshCw, AlertCircle, Radar, Download } from "lucide-react";
import { SignatureCategories } from "@/components/SignatureCategories"; import { SignatureCategories } from "@/components/SignatureCategories";
import { SignatureCategory, useSignatureCategories } from "@/hooks/useSignatureCategories"; import { useSignatureCategories } from "@/hooks/useSignatureCategories";
import { toast } from "@/hooks/use-toast"; import { toast } from "@/hooks/use-toast";
import { CleanModeToggle } from "@/components/CleanModeToggle"; import { CleanModeToggle } from "@/components/CleanModeToggle";
import pb from "@/lib/pocketbase"; import pb from "@/lib/pocketbase";
import { SigviewRecord as Signature } from "@/lib/pbtypes"; import { SigviewRecord as Signature } from "@/lib/pbtypes";
import { useEffect } from "react";
interface SystemTrackerProps { interface SystemTrackerProps {
system: string; system: string;
cleanMode: boolean; cleanMode: boolean;
onCleanModeToggle: (enabled: boolean) => void; onCleanModeToggle: (enabled: boolean) => void;
onDelete?: (signatureId: string) => Promise<void>; onDelete?: (signatureId: string) => Promise<void>;
onUpdate?: (updatedSignature: Partial<Signature>) => Promise<void>;
} }
export const SystemTracker = ({ system, cleanMode, onCleanModeToggle, onDelete }: SystemTrackerProps) => { export const SystemTracker = ({ system, cleanMode, onCleanModeToggle, onDelete, onUpdate }: SystemTrackerProps) => {
const { const {
data: signaturesData, data: signaturesData,
refetch: refetchSignatures, refetch: refetchSignatures,
@@ -148,6 +148,7 @@ export const SystemTracker = ({ system, cleanMode, onCleanModeToggle, onDelete }
categories={categories} categories={categories}
onToggleCategory={toggleCategoryVisibility} onToggleCategory={toggleCategoryVisibility}
onDelete={onDelete} onDelete={onDelete}
onUpdate={onUpdate}
/> />
)} )}
</div> </div>

View File

@@ -71,6 +71,18 @@ export const getSignatureMeta = (type: string): SignatureCategoryMeta => {
return allCategories.get("unknown")!; return allCategories.get("unknown")!;
}; };
export const getSignatureTypes = (): string[] => {
return [
"Combat",
"Homefront",
"Data",
"Relic",
"Gas",
"Ore",
"Wormhole"
];
};
export const categorizeSignatures = (signatures: Map<string, Signature>): Record<string, Signature[]> => { export const categorizeSignatures = (signatures: Map<string, Signature>): Record<string, Signature[]> => {
const categories: Record<string, Signature[]> = { const categories: Record<string, Signature[]> = {
unknown: [], unknown: [],

View File

@@ -89,6 +89,65 @@ export const SystemView = () => {
} }
}; };
const updateSignature = async (updatedSignature: Partial<Signature>): Promise<void> => {
try {
// Get the system ID for the current system
const systemId = await getSystemId(system);
console.log('Updating signature:', {
identifier: updatedSignature.identifier,
systemId,
system,
updatedSignature
});
// Find the signature by identifier and system
const existingRecord = await pb.collection('signature').getFirstListItem(
`identifier='${updatedSignature.identifier}' && system='${systemId}'`
);
console.log('Found existing record:', existingRecord);
// Prepare update data
const updateData: any = {
updated: new Date().toISOString()
};
if (updatedSignature.type !== undefined) {
updateData.type = updatedSignature.type;
}
if (updatedSignature.signame !== undefined) {
updateData.name = updatedSignature.signame; // Map signame to name field
}
if (updatedSignature.dangerous !== undefined) {
updateData.dangerous = updatedSignature.dangerous;
}
if (updatedSignature.scanned !== undefined) {
updateData.scanned = updatedSignature.scanned;
}
console.log('Update data:', updateData);
await pb.collection('signature').update(existingRecord.id, updateData);
// Invalidate queries to refresh the data
queryClient.invalidateQueries({ queryKey: ['signatures', system] });
toast({
title: "Signature Updated",
description: "The signature has been successfully updated.",
});
} catch (error) {
console.error('Failed to update signature:', error);
toast({
title: "Update Failed",
description: error instanceof Error ? error.message : "Failed to update signature.",
variant: "destructive"
});
throw error;
}
};
const handlePaste = async (e: ClipboardEvent) => { const handlePaste = async (e: ClipboardEvent) => {
const pastedText = e.clipboardData?.getData('text'); const pastedText = e.clipboardData?.getData('text');
if (!pastedText?.trim()) return; if (!pastedText?.trim()) return;
@@ -193,6 +252,7 @@ export const SystemView = () => {
cleanMode={cleanMode} cleanMode={cleanMode}
onCleanModeToggle={setCleanMode} onCleanModeToggle={setCleanMode}
onDelete={deleteSignature} onDelete={deleteSignature}
onUpdate={updateSignature}
/> />
</div> </div>