Skip to content

Commit 34c5df7

Browse files
authored
Feature log details (#4)
* Feature log details
1 parent 5921e88 commit 34c5df7

File tree

8 files changed

+380
-20
lines changed

8 files changed

+380
-20
lines changed

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,13 @@ jobs:
127127
with:
128128
path: ./artifacts
129129

130-
- name: Create Draft Release 0.1.1
130+
- name: Create Draft Release 0.1.2
131131
uses: softprops/action-gh-release@v1
132132
with:
133-
tag_name: 0.1.1
134-
name: Release 0.1.1
133+
tag_name: 0.1.2
134+
name: Release 0.1.2
135135
body: |
136-
Automated release for Nginx WAF Desktop Client v0.1.0.
136+
Automated release for Nginx WAF Desktop Client v0.1.2.
137137
138138
## Changes
139139
- Cross-platform builds for Linux x86_64, Windows x86_64, Mac Intel, Mac ARM.

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
# Logs
2-
logs
32
*.log
43
npm-debug.log*
54
yarn-debug.log*

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "Nginx_WAF"
3-
version = "0.1.0"
3+
version = "0.1.2"
44
description = "Nginx WAF - Advanced Nginx Management Platform"
55
authors = ["TinyActive"]
66
edition = "2024"

src-tauri/tauri.conf.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"$schema": "https://schema.tauri.app/config/2",
33
"productName": "Nginx WAF",
4-
"version": "0.1.1",
4+
"version": "0.1.2",
55
"identifier": "com.tinyactive.nginx-waf",
66
"build": {
77
"beforeDevCommand": "npm run dev",
Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
import {
2+
Dialog,
3+
DialogContent,
4+
DialogDescription,
5+
DialogHeader,
6+
DialogTitle,
7+
} from "@/components/ui/dialog";
8+
import { Badge } from "@/components/ui/badge";
9+
import { ScrollArea } from "@/components/ui/scroll-area";
10+
import { LogEntry } from "@/types";
11+
12+
interface LogDetailsDialogProps {
13+
log: LogEntry | null;
14+
open: boolean;
15+
onOpenChange: (open: boolean) => void;
16+
}
17+
18+
export function LogDetailsDialog({ log, open, onOpenChange }: LogDetailsDialogProps) {
19+
if (!log) return null;
20+
21+
const getLevelColor = (
22+
level: string
23+
): "destructive" | "default" | "secondary" | "outline" => {
24+
switch (level) {
25+
case "error":
26+
return "destructive";
27+
case "warning":
28+
return "outline";
29+
case "info":
30+
return "default";
31+
default:
32+
return "secondary";
33+
}
34+
};
35+
36+
const getTypeColor = (type: string) => {
37+
switch (type) {
38+
case "access":
39+
return "default";
40+
case "error":
41+
return "destructive";
42+
case "system":
43+
return "secondary";
44+
default:
45+
return "outline";
46+
}
47+
};
48+
49+
return (
50+
<Dialog open={open} onOpenChange={onOpenChange}>
51+
<DialogContent className="max-w-4xl max-h-[90vh]">
52+
<DialogHeader>
53+
<DialogTitle className="flex items-center gap-2">
54+
Log Details
55+
<Badge variant={getLevelColor(log.level)}>{log.level}</Badge>
56+
<Badge variant={getTypeColor(log.type)}>{log.type}</Badge>
57+
</DialogTitle>
58+
<DialogDescription>
59+
{new Date(log.timestamp).toLocaleString()}
60+
</DialogDescription>
61+
</DialogHeader>
62+
63+
<ScrollArea className="h-[60vh] w-full rounded-md border p-4">
64+
<div className="space-y-4">
65+
{/* Basic Information */}
66+
<div>
67+
<h3 className="text-sm font-semibold mb-2">Basic Information</h3>
68+
<div className="grid grid-cols-2 gap-2 text-sm">
69+
<div>
70+
<span className="font-medium">Source:</span> {log.source}
71+
</div>
72+
<div>
73+
<span className="font-medium">Timestamp:</span>{" "}
74+
{new Date(log.timestamp).toLocaleString()}
75+
</div>
76+
{log.domain && (
77+
<div>
78+
<span className="font-medium">Domain:</span>{" "}
79+
<Badge variant="outline" className="font-mono">
80+
{log.domain}
81+
</Badge>
82+
</div>
83+
)}
84+
{log.ip && (
85+
<div>
86+
<span className="font-medium">IP Address:</span> {log.ip}
87+
</div>
88+
)}
89+
</div>
90+
</div>
91+
92+
{/* Request Information */}
93+
{(log.method || log.path || log.uri || log.statusCode) && (
94+
<div>
95+
<h3 className="text-sm font-semibold mb-2">Request Information</h3>
96+
<div className="grid grid-cols-2 gap-2 text-sm">
97+
{log.method && (
98+
<div>
99+
<span className="font-medium">Method:</span>{" "}
100+
<Badge variant="outline">{log.method}</Badge>
101+
</div>
102+
)}
103+
{log.path && (
104+
<div>
105+
<span className="font-medium">Path:</span>{" "}
106+
<code className="text-xs bg-muted px-1 py-0.5 rounded">
107+
{log.path}
108+
</code>
109+
</div>
110+
)}
111+
{log.uri && (
112+
<div className="col-span-2">
113+
<span className="font-medium">URI:</span>{" "}
114+
<code className="text-xs bg-muted px-1 py-0.5 rounded">
115+
{log.uri}
116+
</code>
117+
</div>
118+
)}
119+
{log.statusCode && (
120+
<div>
121+
<span className="font-medium">Status Code:</span>{" "}
122+
<Badge
123+
variant={
124+
log.statusCode >= 500
125+
? "destructive"
126+
: log.statusCode >= 400
127+
? "outline"
128+
: "default"
129+
}
130+
>
131+
{log.statusCode}
132+
</Badge>
133+
</div>
134+
)}
135+
{log.responseTime && (
136+
<div>
137+
<span className="font-medium">Response Time:</span>{" "}
138+
{log.responseTime}ms
139+
</div>
140+
)}
141+
</div>
142+
</div>
143+
)}
144+
145+
{/* ModSecurity Specific Information */}
146+
{(log.ruleId || log.severity || log.tags || log.file || log.uniqueId) && (
147+
<div>
148+
<h3 className="text-sm font-semibold mb-2">
149+
ModSecurity WAF Details
150+
</h3>
151+
<div className="space-y-2 text-sm">
152+
{log.ruleId && (
153+
<div className="flex items-start gap-2">
154+
<span className="font-medium min-w-[100px]">Rule ID:</span>
155+
<Badge variant="destructive" className="font-mono">
156+
{log.ruleId}
157+
</Badge>
158+
</div>
159+
)}
160+
{log.severity && (
161+
<div className="flex items-start gap-2">
162+
<span className="font-medium min-w-[100px]">Severity:</span>
163+
<Badge
164+
variant={
165+
parseInt(log.severity) >= 3
166+
? "destructive"
167+
: parseInt(log.severity) >= 2
168+
? "outline"
169+
: "default"
170+
}
171+
>
172+
Level {log.severity}
173+
</Badge>
174+
</div>
175+
)}
176+
{log.tags && log.tags.length > 0 && (
177+
<div className="flex items-start gap-2">
178+
<span className="font-medium min-w-[100px]">Tags:</span>
179+
<div className="flex flex-wrap gap-1">
180+
{log.tags.map((tag, index) => (
181+
<Badge key={index} variant="secondary" className="text-xs">
182+
{tag}
183+
</Badge>
184+
))}
185+
</div>
186+
</div>
187+
)}
188+
{log.file && (
189+
<div className="flex items-start gap-2">
190+
<span className="font-medium min-w-[100px]">Rule File:</span>
191+
<code className="text-xs bg-muted px-2 py-1 rounded flex-1 break-all">
192+
{log.file}
193+
</code>
194+
</div>
195+
)}
196+
{log.line && (
197+
<div className="flex items-start gap-2">
198+
<span className="font-medium min-w-[100px]">Line Number:</span>
199+
<span>{log.line}</span>
200+
</div>
201+
)}
202+
{log.uniqueId && (
203+
<div className="flex items-start gap-2">
204+
<span className="font-medium min-w-[100px]">Unique ID:</span>
205+
<code className="text-xs bg-muted px-2 py-1 rounded">
206+
{log.uniqueId}
207+
</code>
208+
</div>
209+
)}
210+
{log.data && (
211+
<div className="flex items-start gap-2">
212+
<span className="font-medium min-w-[100px]">Data:</span>
213+
<code className="text-xs bg-muted px-2 py-1 rounded flex-1 break-all">
214+
{log.data}
215+
</code>
216+
</div>
217+
)}
218+
</div>
219+
</div>
220+
)}
221+
222+
{/* Message */}
223+
<div>
224+
<h3 className="text-sm font-semibold mb-2">Message</h3>
225+
<div className="bg-muted p-3 rounded-md">
226+
<p className="text-sm font-medium mb-2">{log.message}</p>
227+
</div>
228+
</div>
229+
230+
{/* Full Log Entry */}
231+
{log.fullMessage && (
232+
<div>
233+
<h3 className="text-sm font-semibold mb-2">Complete Log Entry</h3>
234+
<div className="bg-muted p-3 rounded-md">
235+
<pre className="text-xs whitespace-pre-wrap break-words font-mono">
236+
{log.fullMessage}
237+
</pre>
238+
</div>
239+
</div>
240+
)}
241+
</div>
242+
</ScrollArea>
243+
</DialogContent>
244+
</Dialog>
245+
);
246+
}

0 commit comments

Comments
 (0)