fix: mount RollbackAlert, fix WifiPanel useEffect, remove unused PoolPanel prop

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jason Staack
2026-03-15 23:17:07 -05:00
parent 091c19c434
commit 874542f802
3 changed files with 28 additions and 10 deletions

View File

@@ -170,7 +170,6 @@ export function PoolPanel({ tenantId, deviceId, active }: ConfigPanelProps) {
entries={typedEntries} entries={typedEntries}
panel={panel} panel={panel}
poolUsedBy={poolUsedBy} poolUsedBy={poolUsedBy}
existingPools={typedEntries.map((e) => e.name).filter(Boolean)}
/> />
{/* Change Preview Modal */} {/* Change Preview Modal */}
@@ -197,13 +196,10 @@ function PoolTable({
entries, entries,
panel, panel,
poolUsedBy, poolUsedBy,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
existingPools: _existingPools,
}: { }: {
entries: PoolEntry[] entries: PoolEntry[]
panel: PanelHook panel: PanelHook
poolUsedBy: Record<string, string[]> poolUsedBy: Record<string, string[]>
existingPools: string[]
}) { }) {
const [dialogOpen, setDialogOpen] = useState(false) const [dialogOpen, setDialogOpen] = useState(false)
const [editing, setEditing] = useState<PoolEntry | null>(null) const [editing, setEditing] = useState<PoolEntry | null>(null)

View File

@@ -9,7 +9,7 @@
* 2. Security Profiles (RouterOS 6 only) -- authentication, passphrases * 2. Security Profiles (RouterOS 6 only) -- authentication, passphrases
*/ */
import { useState, useMemo, useCallback } from 'react' import { useState, useMemo, useCallback, useEffect } from 'react'
import { import {
Wifi, Wifi,
Plus, Plus,
@@ -629,9 +629,7 @@ function WirelessEditDialog({
}) })
// Reset form when entry changes // Reset form when entry changes
// eslint-disable-next-line @typescript-eslint/no-unused-vars useEffect(() => {
const _entryId = entry?.['.id'] || ''
useState(() => {
if (entry) { if (entry) {
setFormData({ setFormData({
ssid: entry.ssid || entry['configuration.ssid'] || '', ssid: entry.ssid || entry['configuration.ssid'] || '',
@@ -643,7 +641,7 @@ function WirelessEditDialog({
'security.passphrase': entry['security.passphrase'] || '', 'security.passphrase': entry['security.passphrase'] || '',
}) })
} }
}) }, [entry])
// Use effect-like pattern to reset form on dialog open // Use effect-like pattern to reset form on dialog open
const handleOpenChange = useCallback((nextOpen: boolean) => { const handleOpenChange = useCallback((nextOpen: boolean) => {

View File

@@ -18,7 +18,7 @@ import {
ShieldOff, ShieldOff,
Shield, Shield,
} from 'lucide-react' } from 'lucide-react'
import { devicesApi, deviceGroupsApi, deviceTagsApi, tenantsApi, type DeviceResponse, type DeviceUpdate } from '@/lib/api' import { devicesApi, deviceGroupsApi, deviceTagsApi, tenantsApi, configApi, type DeviceResponse, type DeviceUpdate } from '@/lib/api'
import { alertsApi } from '@/lib/alertsApi' import { alertsApi } from '@/lib/alertsApi'
import { useAuth, canWrite, canDelete } from '@/lib/auth' import { useAuth, canWrite, canDelete } from '@/lib/auth'
import { toast } from '@/components/ui/toast' import { toast } from '@/components/ui/toast'
@@ -59,6 +59,7 @@ import { SimpleConfigView } from '@/components/simple-config/SimpleConfigView'
import { WinBoxButton } from '@/components/fleet/WinBoxButton' import { WinBoxButton } from '@/components/fleet/WinBoxButton'
import { RemoteWinBoxButton } from '@/components/fleet/RemoteWinBoxButton' import { RemoteWinBoxButton } from '@/components/fleet/RemoteWinBoxButton'
import { SSHTerminal } from '@/components/fleet/SSHTerminal' import { SSHTerminal } from '@/components/fleet/SSHTerminal'
import { RollbackAlert } from '@/components/config/RollbackAlert'
export const Route = createFileRoute( export const Route = createFileRoute(
'/_authenticated/tenants/$tenantId/devices/$deviceId', '/_authenticated/tenants/$tenantId/devices/$deviceId',
@@ -348,6 +349,21 @@ function DeviceDetailPage() {
queryFn: () => tenantsApi.get(tenantId), queryFn: () => tenantsApi.get(tenantId),
}) })
const { data: backups } = useQuery({
queryKey: ['config-backups', tenantId, deviceId],
queryFn: () => configApi.listBackups(tenantId, deviceId),
})
// True if a pre-restore backup was created within the last 30 minutes,
// indicating a config push just happened before the device went offline.
const hasRecentPushAlert = backups
? backups.some((b) => {
if (b.trigger_type !== 'pre-restore') return false
const age = Date.now() - new Date(b.created_at).getTime()
return age < 30 * 60 * 1000
})
: false
const { data: groups } = useQuery({ const { data: groups } = useQuery({
queryKey: ['device-groups', tenantId], queryKey: ['device-groups', tenantId],
queryFn: () => deviceGroupsApi.list(tenantId), queryFn: () => deviceGroupsApi.list(tenantId),
@@ -482,6 +498,14 @@ function DeviceDetailPage() {
</div> </div>
</div> </div>
{/* Emergency rollback banner */}
<RollbackAlert
tenantId={tenantId}
deviceId={deviceId}
deviceStatus={device.status}
hasRecentPushAlert={hasRecentPushAlert}
/>
{/* Config View (Simple or Standard) */} {/* Config View (Simple or Standard) */}
<SimpleConfigView <SimpleConfigView
tenantId={tenantId} tenantId={tenantId}