From 695742bfcfcd2389f5faa1c585d603da9c8f6f24 Mon Sep 17 00:00:00 2001 From: Sam Freund Date: Sat, 1 Nov 2025 16:48:28 -0500 Subject: [PATCH] Add axios post util (#2153) ## Description This replaces boilerplate that checks whether we've successfully sent the request, whether there was an error, etc. closes #2151 ## 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 --- .../components/cameras/CameraSettingsCard.vue | 36 +--- .../components/settings/DeviceControlCard.vue | 151 ++------------ .../settings/ObjectDetectionCard.vue | 197 ++++-------------- photon-client/src/lib/PhotonUtils.ts | 40 ++++ .../src/views/CameraMatchingView.vue | 127 ++--------- 5 files changed, 116 insertions(+), 435 deletions(-) diff --git a/photon-client/src/components/cameras/CameraSettingsCard.vue b/photon-client/src/components/cameras/CameraSettingsCard.vue index 18d760bcf..c819b60c2 100644 --- a/photon-client/src/components/cameras/CameraSettingsCard.vue +++ b/photon-client/src/components/cameras/CameraSettingsCard.vue @@ -6,8 +6,8 @@ import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore"; import { useStateStore } from "@/stores/StateStore"; import { computed, ref, watchEffect } from "vue"; import { type CameraSettingsChangeRequest, ValidQuirks } from "@/types/SettingTypes"; -import axios from "axios"; import { useTheme } from "vuetify"; +import { axiosPost } from "@/lib/PhotonUtils"; const theme = useTheme(); @@ -120,36 +120,10 @@ const deleteThisCamera = () => { const payload = { cameraUniqueName: useStateStore().currentCameraUniqueName }; - axios - .post("/utils/nukeOneCamera", payload) - .then(() => { - useStateStore().showSnackbarMessage({ - message: "Successfully dispatched the delete command. Waiting for backend to start back up", - color: "success" - }); - }) - .catch((error) => { - if (error.response) { - useStateStore().showSnackbarMessage({ - message: "The backend is unable to fulfil the request to delete this camera.", - color: "error" - }); - } else if (error.request) { - useStateStore().showSnackbarMessage({ - message: "Error while trying to process the request! The backend didn't respond.", - color: "error" - }); - } else { - useStateStore().showSnackbarMessage({ - message: "An error occurred while trying to process the request.", - color: "error" - }); - } - }) - .finally(() => { - deletingCamera.value = false; - showDeleteCamera.value = false; - }); + axiosPost("/utils/nukeOneCamera", "delete this camera", payload).finally(() => { + deletingCamera.value = false; + showDeleteCamera.value = false; + }); }; const wrappedCameras = computed(() => Object.keys(useCameraSettingsStore().cameras).map((cameraUniqueName) => ({ diff --git a/photon-client/src/components/settings/DeviceControlCard.vue b/photon-client/src/components/settings/DeviceControlCard.vue index 76783f6dc..7df24b3b3 100644 --- a/photon-client/src/components/settings/DeviceControlCard.vue +++ b/photon-client/src/components/settings/DeviceControlCard.vue @@ -3,59 +3,16 @@ import { inject, ref } from "vue"; import { useStateStore } from "@/stores/StateStore"; import PvSelect from "@/components/common/pv-select.vue"; import PvInput from "@/components/common/pv-input.vue"; -import axios from "axios"; import { useTheme } from "vuetify"; +import { axiosPost } from "@/lib/PhotonUtils"; const theme = useTheme(); const restartProgram = () => { - axios - .post("/utils/restartProgram") - .then(() => { - useStateStore().showSnackbarMessage({ message: "Successfully sent program restart request", color: "success" }); - }) - .catch((error) => { - // This endpoint always return 204 regardless of outcome - if (error.request) { - useStateStore().showSnackbarMessage({ - message: "Error while trying to process the request! The backend didn't respond.", - color: "error" - }); - } else { - useStateStore().showSnackbarMessage({ - message: "An error occurred while trying to process the request.", - color: "error" - }); - } - }); + axiosPost("/utils/restartProgram", "restart PhotonVision"); }; const restartDevice = () => { - axios - .post("/utils/restartDevice") - .then(() => { - useStateStore().showSnackbarMessage({ - message: "Successfully dispatched the restart command. It isn't confirmed if a device restart will occur.", - color: "success" - }); - }) - .catch((error) => { - if (error.response) { - useStateStore().showSnackbarMessage({ - message: "The backend is unable to fulfil the request to restart the device.", - color: "error" - }); - } else if (error.request) { - useStateStore().showSnackbarMessage({ - message: "Error while trying to process the request! The backend didn't respond.", - color: "error" - }); - } else { - useStateStore().showSnackbarMessage({ - message: "An error occurred while trying to process the request.", - color: "error" - }); - } - }); + axiosPost("/utils/restartDevice", "restart the device"); }; const address = inject("backendHost"); @@ -77,47 +34,25 @@ const handleOfflineUpdate = () => { timeout: -1 }); - axios - .post("/utils/offlineUpdate", formData, { - headers: { "Content-Type": "multipart/form-data" }, - onUploadProgress: ({ progress }) => { - const uploadPercentage = (progress || 0) * 100.0; - if (uploadPercentage < 99.5) { - useStateStore().showSnackbarMessage({ - message: "New Software Upload in Process, " + uploadPercentage.toFixed(2) + "% complete", - color: "secondary", - timeout: -1 - }); - } else { - useStateStore().showSnackbarMessage({ - message: "Installing uploaded software...", - color: "secondary", - timeout: -1 - }); - } - } - }) - .then((response) => { - useStateStore().showSnackbarMessage({ message: response.data.text || response.data, color: "success" }); - }) - .catch((error) => { - if (error.response) { + axiosPost("/utils/offlineUpdate", "upload new software", formData, { + headers: { "Content-Type": "multipart/form-data" }, + onUploadProgress: ({ progress }) => { + const uploadPercentage = (progress || 0) * 100.0; + if (uploadPercentage < 99.5) { useStateStore().showSnackbarMessage({ - color: "error", - message: error.response.data.text || error.response.data - }); - } else if (error.request) { - useStateStore().showSnackbarMessage({ - color: "error", - message: "Error while trying to process the request! The backend didn't respond." + message: "New Software Upload in Process, " + uploadPercentage.toFixed(2) + "% complete", + color: "secondary", + timeout: -1 }); } else { useStateStore().showSnackbarMessage({ - color: "error", - message: "An error occurred while trying to process the request." + message: "Installing uploaded software...", + color: "secondary", + timeout: -1 }); } - }); + } + }); }; const exportLogFile = ref(); @@ -166,29 +101,9 @@ const handleSettingsImport = () => { break; } - axios - .post(`/settings${settingsEndpoint}`, formData, { headers: { "Content-Type": "multipart/form-data" } }) - .then((response) => { - useStateStore().showSnackbarMessage({ message: response.data.text || response.data, color: "success" }); - }) - .catch((error) => { - if (error.response) { - useStateStore().showSnackbarMessage({ - color: "error", - message: error.response.data.text || error.response.data - }); - } else if (error.request) { - useStateStore().showSnackbarMessage({ - color: "error", - message: "Error while trying to process the request! The backend didn't respond." - }); - } else { - useStateStore().showSnackbarMessage({ - color: "error", - message: "An error occurred while trying to process the request." - }); - } - }); + axiosPost(`/settings${settingsEndpoint}`, "import settings", formData, { + headers: { "Content-Type": "multipart/form-data" } + }); showImportDialog.value = false; importType.value = undefined; @@ -199,32 +114,8 @@ const showFactoryReset = ref(false); const expected = "Delete Everything"; const yesDeleteMySettingsText = ref(""); const nukePhotonConfigDirectory = () => { - axios - .post("/utils/nukeConfigDirectory") - .then(() => { - useStateStore().showSnackbarMessage({ - message: "Successfully dispatched the reset command. Waiting for backend to start back up", - color: "success" - }); - }) - .catch((error) => { - if (error.response) { - useStateStore().showSnackbarMessage({ - message: "The backend is unable to fulfill the request to reset the device.", - color: "error" - }); - } else if (error.request) { - useStateStore().showSnackbarMessage({ - message: "Error while trying to process the request! The backend didn't respond.", - color: "error" - }); - } else { - useStateStore().showSnackbarMessage({ - message: "An error occurred while trying to process the request.", - color: "error" - }); - } - }); + axiosPost("/utils/nukeConfigDirectory", "delete the config directory"); + showFactoryReset.value = false; }; diff --git a/photon-client/src/components/settings/ObjectDetectionCard.vue b/photon-client/src/components/settings/ObjectDetectionCard.vue index d135b5748..fd7a3de26 100644 --- a/photon-client/src/components/settings/ObjectDetectionCard.vue +++ b/photon-client/src/components/settings/ObjectDetectionCard.vue @@ -1,11 +1,11 @@