generated from Dicken/dickendock
round63: Geraeteuebergreifende Sichtbarkeit fuer manuelle Einzelgeraete-Scans, automatische Logs-Aktualisierung danach
This commit is contained in:
@@ -21,6 +21,7 @@ import {
|
|||||||
requestCancel,
|
requestCancel,
|
||||||
tryLockDevice,
|
tryLockDevice,
|
||||||
unlockDevice,
|
unlockDevice,
|
||||||
|
getScanningDeviceIds,
|
||||||
} from "../scanJobs.js";
|
} from "../scanJobs.js";
|
||||||
import type { Device } from "@launchpad/shared";
|
import type { Device } from "@launchpad/shared";
|
||||||
|
|
||||||
@@ -271,6 +272,15 @@ export async function scanRoutes(app: FastifyInstance): Promise<void> {
|
|||||||
return { dismissed: true };
|
return { dismissed: true };
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Geräteübergreifende Sichtbarkeit für manuelle Einzelgeräte-Scans (siehe
|
||||||
|
// getScanningDeviceIds() in scanJobs.ts) - wird von der Seitenleiste
|
||||||
|
// gepollt, damit "Ein Scan läuft gerade" auch für einen per Button auf der
|
||||||
|
// Geräteseite gestarteten Scan angezeigt wird, nicht nur für den
|
||||||
|
// Sammel-Scan.
|
||||||
|
app.get("/api/scan/devices/active", async () => {
|
||||||
|
return { deviceIds: getScanningDeviceIds() };
|
||||||
|
});
|
||||||
|
|
||||||
app.post("/api/scan/devices/:id", async (request, reply) => {
|
app.post("/api/scan/devices/:id", async (request, reply) => {
|
||||||
const { id } = request.params as { id: string };
|
const { id } = request.params as { id: string };
|
||||||
const { full } = request.query as { full?: string };
|
const { full } = request.query as { full?: string };
|
||||||
|
|||||||
@@ -100,3 +100,18 @@ export function tryLockDevice(deviceId: string): boolean {
|
|||||||
export function unlockDevice(deviceId: string): void {
|
export function unlockDevice(deviceId: string): void {
|
||||||
devicesCurrentlyScanning.delete(deviceId);
|
devicesCurrentlyScanning.delete(deviceId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Liefert die IDs aller Geräte, die GERADE JETZT gescannt werden - egal ob
|
||||||
|
* über den Einzelgerät-Endpunkt (manueller "Jetzt scannen"-Button auf der
|
||||||
|
* Geräteseite) oder als Teil eines laufenden Sammel-Scans. Genutzt für die
|
||||||
|
* geräteübergreifende Anzeige "Ein Scan läuft gerade" in der Seitenleiste
|
||||||
|
* (siehe AdminLayout.tsx/useScanActivity.ts) - vorher war ein einzelner
|
||||||
|
* manueller Geräte-Scan NUR im Browser sichtbar, der ihn ausgelöst hat (der
|
||||||
|
* Einzelgerät-Endpunkt ist eine simple, blockierende Anfrage ohne eigenen
|
||||||
|
* Job-Status wie der Sammel-Scan), auf jedem anderen Browser/Gerät gab es
|
||||||
|
* dafür überhaupt keine Anzeige.
|
||||||
|
*/
|
||||||
|
export function getScanningDeviceIds(): string[] {
|
||||||
|
return Array.from(devicesCurrentlyScanning);
|
||||||
|
}
|
||||||
|
|||||||
@@ -22,18 +22,29 @@ export function useScanActivity(): ScanActivity {
|
|||||||
|
|
||||||
async function poll() {
|
async function poll() {
|
||||||
try {
|
try {
|
||||||
const [devicesRes, apisRes, fritzboxRes] = await Promise.all([
|
const [devicesRes, apisRes, fritzboxRes, activeDevicesRes] = await Promise.all([
|
||||||
fetch("/api/scan/devices/all/status"),
|
fetch("/api/scan/devices/all/status"),
|
||||||
fetch("/api/scan/apis/status"),
|
fetch("/api/scan/apis/status"),
|
||||||
fetch("/api/scan/fritzbox/status"),
|
fetch("/api/scan/fritzbox/status"),
|
||||||
|
fetch("/api/scan/devices/active"),
|
||||||
]);
|
]);
|
||||||
if (cancelled) return;
|
if (cancelled) return;
|
||||||
|
|
||||||
const devicesStatus = devicesRes.ok ? await devicesRes.json() : null;
|
const devicesStatus = devicesRes.ok ? await devicesRes.json() : null;
|
||||||
const apisStatus = apisRes.ok ? await apisRes.json() : null;
|
const apisStatus = apisRes.ok ? await apisRes.json() : null;
|
||||||
const fritzboxStatus = fritzboxRes.ok ? await fritzboxRes.json() : null;
|
const fritzboxStatus = fritzboxRes.ok ? await fritzboxRes.json() : null;
|
||||||
|
// Manuelle Einzelgeräte-Scans (Button auf der Geräteseite) laufen
|
||||||
|
// NICHT über den Sammel-Scan-Job, sondern über eine einfache,
|
||||||
|
// blockierende Anfrage - ohne diesen zusätzlichen Abruf wäre so ein
|
||||||
|
// Scan für jeden anderen Browser/jedes andere Gerät unsichtbar
|
||||||
|
// gewesen (siehe Bugreport).
|
||||||
|
const activeDevices = activeDevicesRes.ok ? await activeDevicesRes.json() : null;
|
||||||
|
|
||||||
const running = !!devicesStatus?.running || !!apisStatus?.running || !!fritzboxStatus?.running;
|
const running =
|
||||||
|
!!devicesStatus?.running ||
|
||||||
|
!!apisStatus?.running ||
|
||||||
|
!!fritzboxStatus?.running ||
|
||||||
|
(activeDevices?.deviceIds?.length ?? 0) > 0;
|
||||||
|
|
||||||
const lastResult = devicesStatus?.lastResult;
|
const lastResult = devicesStatus?.lastResult;
|
||||||
const pendingCount = lastResult
|
const pendingCount = lastResult
|
||||||
|
|||||||
@@ -343,9 +343,16 @@ function DeviceRow({ device }: { device: DeviceWithServices }) {
|
|||||||
setDeviceNameSuggestion(result.deviceNameSuggestion);
|
setDeviceNameSuggestion(result.deviceNameSuggestion);
|
||||||
queryClient.invalidateQueries({ queryKey: ["devices"] });
|
queryClient.invalidateQueries({ queryKey: ["devices"] });
|
||||||
queryClient.invalidateQueries({ queryKey: ["services"] });
|
queryClient.invalidateQueries({ queryKey: ["services"] });
|
||||||
|
// War bisher vergessen: der Scan selbst schreibt zwar schon einen
|
||||||
|
// Log-Eintrag (siehe performDeviceScan in routes/scan.ts, gilt für
|
||||||
|
// Einzelgerät- UND Sammel-Scan gleichermaßen), aber ohne diese
|
||||||
|
// Invalidierung blieb eine bereits geöffnete Admin -> Logs-Seite auf
|
||||||
|
// dem alten Stand, bis man sie manuell neu lädt (siehe Bugreport).
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["logs"] });
|
||||||
},
|
},
|
||||||
onError: (err: Error) => {
|
onError: (err: Error) => {
|
||||||
setScanMessage(err.name === "AbortError" ? "Scan abgebrochen." : err.message);
|
setScanMessage(err.name === "AbortError" ? "Scan abgebrochen." : err.message);
|
||||||
|
queryClient.invalidateQueries({ queryKey: ["logs"] });
|
||||||
},
|
},
|
||||||
onSettled: () => setScanAbort(null),
|
onSettled: () => setScanAbort(null),
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user