From 6c9a142622f99db5541591bfb4c4b4ba07fc6ac7 Mon Sep 17 00:00:00 2001 From: Sam Freund Date: Mon, 19 Jan 2026 13:58:23 -0600 Subject: [PATCH] Propagate changes after modifying OD model (#2299) ## Description This PR adjusts how model modification is handled. Any updates to metadata, or deletion is handled in the frontend after sending data to the backend. Any creation of models occurs in the backend, and we push an update to the frontend. This PR also fixes a typo in PhotonUtils which meant we hit the wrong endpoint when an IP was passed into the status check. ## Meta Merge checklist: - [x] Pull Request title is [short, imperative summary](https://cbea.ms/git-commit/) of proposed changes - [x] The description documents the _what_ and _why_ - [ ] If this PR changes behavior or adds a feature, user documentation is updated - [ ] If this PR touches photon-serde, all messages have been regenerated and hashes have not changed unexpectedly - [ ] If this PR touches configuration, this is backwards compatible with settings back to v2025.3.2 - [ ] If this PR touches pipeline settings or anything related to data exchange, the frontend typing is updated - [ ] If this PR addresses a bug, a regression test for it is added --- .../settings/ObjectDetectionCard.vue | 6 ++-- photon-client/src/lib/PhotonUtils.ts | 2 +- .../photonvision/server/RequestHandler.java | 30 +++++++++++++++---- 3 files changed, 28 insertions(+), 10 deletions(-) diff --git a/photon-client/src/components/settings/ObjectDetectionCard.vue b/photon-client/src/components/settings/ObjectDetectionCard.vue index db6e9d419..0aa8f00c8 100644 --- a/photon-client/src/components/settings/ObjectDetectionCard.vue +++ b/photon-client/src/components/settings/ObjectDetectionCard.vue @@ -26,7 +26,7 @@ const importWidth = ref(null); const importVersion = ref(null); // TODO gray out the button when model is uploading -const handleImport = async () => { +const handleImport = () => { if (importModelFile.value === null) return; const formData = new FormData(); @@ -72,13 +72,13 @@ const handleImport = async () => { importVersion.value = null; }; -const deleteModel = async (model: ObjectDetectionModelProperties) => { +const deleteModel = (model: ObjectDetectionModelProperties) => { axiosPost("/objectdetection/delete", "delete an object detection model", { modelPath: model.modelPath }); }; -const renameModel = async (model: ObjectDetectionModelProperties, newName: string) => { +const renameModel = (model: ObjectDetectionModelProperties, newName: string) => { useStateStore().showSnackbarMessage({ message: "Renaming Object Detection Model...", color: "secondary", diff --git a/photon-client/src/lib/PhotonUtils.ts b/photon-client/src/lib/PhotonUtils.ts index 805f4731c..04af8ba19 100644 --- a/photon-client/src/lib/PhotonUtils.ts +++ b/photon-client/src/lib/PhotonUtils.ts @@ -22,7 +22,7 @@ export const statusCheck = async (timeout: number, ip?: string): Promise 0) { try { pollLimit--; - await axios.get(ip ? `http://${ip}/status` : "/status"); + await axios.get(ip ? `http://${ip}/api/status` : "/status"); return true; } catch { // Backend not ready yet, wait and retry diff --git a/photon-server/src/main/java/org/photonvision/server/RequestHandler.java b/photon-server/src/main/java/org/photonvision/server/RequestHandler.java index 350ec04bf..63ffd2ec3 100644 --- a/photon-server/src/main/java/org/photonvision/server/RequestHandler.java +++ b/photon-server/src/main/java/org/photonvision/server/RequestHandler.java @@ -852,6 +852,12 @@ public class RequestHandler { ctx.result("There was an error while saving the uploaded object detection models"); logger.error("There was an error while saving the uploaded object detection models"); } + + DataChangeService.getInstance() + .publishEvent( + new OutgoingUIEvent<>( + "fullsettings", + UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig()))); } private record DeleteObjectDetectionModelRequest(Path modelPath) {} @@ -898,17 +904,17 @@ public class RequestHandler { ctx.status(200).result("Successfully deleted object detection model"); + DataChangeService.getInstance() + .publishEvent( + new OutgoingUIEvent<>( + "fullsettings", + UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig()))); + } catch (Exception e) { ctx.status(500); ctx.result("Error deleting object detection model: " + e.getMessage()); logger.error("Error deleting object detection model", e); } - - DataChangeService.getInstance() - .publishEvent( - new OutgoingUIEvent<>( - "fullsettings", - UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig()))); } private record RenameObjectDetectionModelRequest(Path modelPath, String newName) {} @@ -951,6 +957,12 @@ public class RequestHandler { NeuralNetworkModelManager.getInstance().discoverModels(); ctx.status(200).result("Successfully renamed object detection model"); + + DataChangeService.getInstance() + .publishEvent( + new OutgoingUIEvent<>( + "fullsettings", + UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig()))); } catch (Exception e) { ctx.status(500); ctx.result("Error renaming object detection model: " + e.getMessage()); @@ -970,6 +982,12 @@ public class RequestHandler { ctx.result("Error clearing object detection models: " + e.getMessage()); logger.error("Error clearing object detection models", e); } + + DataChangeService.getInstance() + .publishEvent( + new OutgoingUIEvent<>( + "fullsettings", + UIPhotonConfiguration.programStateToUi(ConfigManager.getInstance().getConfig()))); } public static void onDeviceRestartRequest(Context ctx) {