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

View File

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

View File

@@ -18,7 +18,7 @@ import {
ShieldOff,
Shield,
} 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 { useAuth, canWrite, canDelete } from '@/lib/auth'
import { toast } from '@/components/ui/toast'
@@ -59,6 +59,7 @@ import { SimpleConfigView } from '@/components/simple-config/SimpleConfigView'
import { WinBoxButton } from '@/components/fleet/WinBoxButton'
import { RemoteWinBoxButton } from '@/components/fleet/RemoteWinBoxButton'
import { SSHTerminal } from '@/components/fleet/SSHTerminal'
import { RollbackAlert } from '@/components/config/RollbackAlert'
export const Route = createFileRoute(
'/_authenticated/tenants/$tenantId/devices/$deviceId',
@@ -348,6 +349,21 @@ function DeviceDetailPage() {
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({
queryKey: ['device-groups', tenantId],
queryFn: () => deviceGroupsApi.list(tenantId),
@@ -482,6 +498,14 @@ function DeviceDetailPage() {
</div>
</div>
{/* Emergency rollback banner */}
<RollbackAlert
tenantId={tenantId}
deviceId={deviceId}
deviceStatus={device.status}
hasRecentPushAlert={hasRecentPushAlert}
/>
{/* Config View (Simple or Standard) */}
<SimpleConfigView
tenantId={tenantId}