22
33import {
44 AlertTriangle ,
5- Ban ,
65 CheckCircle2 ,
76 Clock3 ,
8- Database ,
9- type LucideIcon ,
10- Radio ,
117 ShieldCheck ,
128 XCircle ,
139} from "lucide-react" ;
@@ -106,33 +102,23 @@ function getOverallState(
106102function ComponentStatus ( {
107103 title,
108104 available,
109- icon : Icon ,
110- children,
111105} : {
112106 title : string ;
113107 available : boolean ;
114- icon : LucideIcon ;
115- children ?: React . ReactNode ;
116108} ) {
117109 return (
118- < section className = "space-y-2 p-3" >
119- < div className = "flex items-center justify-between gap-3" >
120- < h3 className = "flex items-center gap-2 font-medium" >
121- < Icon className = "size-4 text-muted-foreground" aria-hidden = "true" />
122- { title }
123- </ h3 >
124- < StatusBadge
125- icon = { available ? CheckCircle2 : XCircle }
126- label = { available ? "Available" : "Unavailable" }
127- className = {
128- available
129- ? "text-emerald-600 dark:text-emerald-400"
130- : "text-destructive"
131- }
132- size = "sm"
133- />
134- </ div >
135- { children }
110+ < section className = "flex items-center justify-between gap-3 p-3" >
111+ < h3 className = "font-medium" > { title } </ h3 >
112+ < StatusBadge
113+ icon = { available ? CheckCircle2 : XCircle }
114+ label = { available ? "Available" : "Unavailable" }
115+ className = {
116+ available
117+ ? "text-emerald-600 dark:text-emerald-400"
118+ : "text-destructive"
119+ }
120+ size = "sm"
121+ />
136122 </ section >
137123 ) ;
138124}
@@ -146,17 +132,6 @@ function DateValue({ value }: { value?: string }) {
146132 ) ;
147133}
148134
149- function formatBouncerError ( error : string ) {
150- switch ( error ) {
151- case "command_failed" :
152- return "CrowdSec status command failed" ;
153- case "invalid_output" :
154- return "CrowdSec returned an invalid status response" ;
155- default :
156- return "CrowdSec bouncer status is unavailable" ;
157- }
158- }
159-
160135export function ServerSecurityPage ( {
161136 serverId,
162137 initialServerStatus,
@@ -190,16 +165,11 @@ export function ServerSecurityPage({
190165 ! health . bouncer . revoked &&
191166 ! isOlderThan ( health . bouncer . lastPullAt , currentTime ) ,
192167 ) ;
193- const bouncerRegistration = health ?. bouncer . revoked
194- ? "Revoked"
195- : health ?. bouncer . registered
196- ? "Registered"
197- : "Missing" ;
198168
199169 return (
200170 < div className = "space-y-4" >
201- < Card >
202- < CardHeader className = "flex-row items-start justify-between gap-4" >
171+ < Card className = "gap-0 py-0" >
172+ < CardHeader className = "flex-row items-start justify-between gap-4 py-4 " >
203173 < div className = "space-y-1" >
204174 < CardTitle className = "flex items-center gap-2 text-lg" >
205175 < ShieldCheck className = "size-5" aria-hidden = "true" />
@@ -211,58 +181,19 @@ export function ServerSecurityPage({
211181 </ div >
212182 < Status state = { overallState } />
213183 </ CardHeader >
214- </ Card >
215-
216- < Card size = "sm" className = "gap-0 py-0" >
217- < CardContent className = "grid divide-y p-0 md:grid-cols-3 md:divide-x md:divide-y-0" >
184+ < CardContent className = "grid divide-y border-t p-0 md:grid-cols-3 md:divide-x md:divide-y-0" >
218185 < ComponentStatus
219186 title = "LAPI"
220187 available = { health ?. lapi . available ?? false }
221- icon = { Database }
222188 />
223189 < ComponentStatus
224190 title = "Traefik acquisition"
225191 available = { health ?. metrics . available ?? false }
226- icon = { Radio }
227- >
228- < dl className = "flex flex-wrap gap-x-4 gap-y-1 text-xs" >
229- { [
230- [ "Read" , health ?. metrics . reads ] ,
231- [ "Parsed" , health ?. metrics . parsed ] ,
232- [ "Unparsed" , health ?. metrics . unparsed ] ,
233- ] . map ( ( [ label , value ] ) => (
234- < div key = { label } className = "flex gap-1.5" >
235- < dt className = "text-muted-foreground" > { label } </ dt >
236- < dd className = "font-mono font-medium tabular-nums" >
237- { value ?? "—" }
238- </ dd >
239- </ div >
240- ) ) }
241- </ dl >
242- </ ComponentStatus >
192+ />
243193 < ComponentStatus
244194 title = "Traefik bouncer"
245195 available = { bouncerAvailable }
246- icon = { Ban }
247- >
248- < dl className = "space-y-1 text-xs" >
249- < div className = "flex justify-between gap-2" >
250- < dt className = "text-muted-foreground" > Registration</ dt >
251- < dd > { bouncerRegistration } </ dd >
252- </ div >
253- < div className = "flex justify-between gap-2" >
254- < dt className = "text-muted-foreground" > Last decision pull</ dt >
255- < dd className = "text-right" >
256- < DateValue value = { health ?. bouncer . lastPullAt } />
257- </ dd >
258- </ div >
259- { health ?. bouncer . error && (
260- < div className = "text-destructive" >
261- { formatBouncerError ( health . bouncer . error ) }
262- </ div >
263- ) }
264- </ dl >
265- </ ComponentStatus >
196+ />
266197 </ CardContent >
267198 </ Card >
268199
0 commit comments