From 1ee5b341580420b0b30b232f78d97201103e252b Mon Sep 17 00:00:00 2001 From: rever-tecnologia Date: Fri, 5 Dec 2025 09:50:11 -0300 Subject: [PATCH] Refactor USB control to modal with improved UX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Move USB policy control from bottom of page to modal dialog - Add "Controle USB" button in device controls section - Show USB chip for all Windows devices (default to ALLOW) - Add close button (X) with hover effect in modal header - Fix all Portuguese accents in USB control component - Position status badge at top of modal content - Add variant prop to UsbPolicyControl (card/inline) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .../admin/devices/admin-devices-overview.tsx | 35 +++++++++--- .../admin/devices/usb-policy-control.tsx | 56 ++++++++++--------- 2 files changed, 57 insertions(+), 34 deletions(-) diff --git a/src/components/admin/devices/admin-devices-overview.tsx b/src/components/admin/devices/admin-devices-overview.tsx index 74732b7..443df72 100644 --- a/src/components/admin/devices/admin-devices-overview.tsx +++ b/src/components/admin/devices/admin-devices-overview.tsx @@ -40,6 +40,7 @@ import { Tablet, Usb, Loader2, + X, } from "lucide-react" import { api } from "@/convex/_generated/api" @@ -53,7 +54,7 @@ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover" import { Checkbox } from "@/components/ui/checkbox" import { Card, CardAction, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" -import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog" +import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog" import { Table, TableBody, @@ -3185,7 +3186,7 @@ export function DeviceDetails({ device }: DeviceDetailsProps) { }) } const isWindowsDevice = (device?.osName ?? "").toLowerCase().includes("windows") - if (isWindowsDevice && device?.usbPolicy) { + if (isWindowsDevice) { const policyLabels: Record = { ALLOW: "Permitido", BLOCK_ALL: "Bloqueado", @@ -3196,10 +3197,11 @@ export function DeviceDetails({ device }: DeviceDetailsProps) { APPLIED: "Aplicado", FAILED: "Falhou", } - const policyLabel = policyLabels[device.usbPolicy] ?? device.usbPolicy - const statusLabel = device.usbPolicyStatus ? ` (${statusLabels[device.usbPolicyStatus] ?? device.usbPolicyStatus})` : "" - const isPending = device.usbPolicyStatus === "PENDING" - const isFailed = device.usbPolicyStatus === "FAILED" + const currentPolicy = device?.usbPolicy ?? "ALLOW" + const policyLabel = policyLabels[currentPolicy] ?? currentPolicy + const statusLabel = device?.usbPolicyStatus ? ` (${statusLabels[device.usbPolicyStatus] ?? device.usbPolicyStatus})` : "" + const isPending = device?.usbPolicyStatus === "PENDING" + const isFailed = device?.usbPolicyStatus === "FAILED" chips.push({ key: "usb-policy", label: "USB", @@ -3934,7 +3936,6 @@ export function DeviceDetails({ device }: DeviceDetailsProps) { value={chip.value} icon={chip.icon} tone={chip.tone} - onClick={chip.key === "usb-policy" && canManageRemoteAccess ? () => setIsUsbModalOpen(true) : undefined} /> ))} @@ -3942,13 +3943,17 @@ export function DeviceDetails({ device }: DeviceDetailsProps) { {/* Modal de Controle USB */} - + + + Fechar + + Controle de USB - {device.displayName ?? device.hostname} - Gerencie as politicas de acesso a dispositivos USB de armazenamento + Gerencie as políticas de acesso a dispositivos USB de armazenamento ) : null} + {canManageRemoteAccess && (device?.osName ?? "").toLowerCase().includes("windows") && ( + + )} diff --git a/src/components/admin/devices/usb-policy-control.tsx b/src/components/admin/devices/usb-policy-control.tsx index d01ba50..6eec555 100644 --- a/src/components/admin/devices/usb-policy-control.tsx +++ b/src/components/admin/devices/usb-policy-control.tsx @@ -137,7 +137,7 @@ export function UsbPolicyControl({ const handleApplyPolicy = async () => { if (selectedPolicy === usbPolicy?.policy) { - toast.info("A politica selecionada ja esta aplicada.") + toast.info("A política selecionada já está aplicada.") return } @@ -150,10 +150,10 @@ export function UsbPolicyControl({ actorEmail, actorName, }) - toast.success("Politica USB enviada para aplicacao.") + toast.success("Política USB enviada para aplicação.") } catch (error) { - console.error("[usb-policy] Falha ao aplicar politica", error) - toast.error("Falha ao aplicar politica USB. Tente novamente.") + console.error("[usb-policy] Falha ao aplicar política", error) + toast.error("Falha ao aplicar política USB. Tente novamente.") } finally { setIsApplying(false) } @@ -168,36 +168,42 @@ export function UsbPolicyControl({ const content = (
-
-
-
- -
-
-

{currentConfig.label}

-

{currentConfig.description}

-
+ {/* Status atual no topo */} + {usbPolicy?.status && ( +
+ Status da política + {getStatusBadge(usbPolicy.status)}
- {usbPolicy?.status && getStatusBadge(usbPolicy.status)} -
+ )} {usbPolicy?.error && (
-

Erro na aplicacao

+

Erro na aplicação

{usbPolicy.error}

)} + {/* Política atual */} +
+
+ +
+
+

{currentConfig.label}

+

{currentConfig.description}

+
+
+
- +