2025-01-01 03:04:20 -05:00
|
|
|
<script setup lang="ts">
|
|
|
|
|
import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";
|
2025-01-14 02:30:25 -05:00
|
|
|
import { computed, inject, ref } from "vue";
|
2025-01-01 03:04:20 -05:00
|
|
|
import { useStateStore } from "@/stores/StateStore";
|
|
|
|
|
import {
|
|
|
|
|
PlaceholderCameraSettings,
|
|
|
|
|
PVCameraInfo,
|
|
|
|
|
type PVCSICameraInfo,
|
|
|
|
|
type PVFileCameraInfo,
|
2025-01-07 08:45:39 -05:00
|
|
|
type PVUsbCameraInfo,
|
|
|
|
|
type UiCameraConfiguration
|
2025-01-01 03:04:20 -05:00
|
|
|
} from "@/types/SettingTypes";
|
|
|
|
|
import { getResolutionString } from "@/lib/PhotonUtils";
|
2025-05-06 18:21:41 -04:00
|
|
|
import PhotonCameraStream from "@/components/app/photon-camera-stream.vue";
|
|
|
|
|
import PvInput from "@/components/common/pv-input.vue";
|
2025-01-01 03:04:20 -05:00
|
|
|
import PvCameraInfoCard from "@/components/common/pv-camera-info-card.vue";
|
|
|
|
|
import axios from "axios";
|
2025-01-07 08:45:39 -05:00
|
|
|
import PvCameraMatchCard from "@/components/common/pv-camera-match-card.vue";
|
|
|
|
|
import type { WebsocketCameraSettingsUpdate } from "@/types/WebsocketDataTypes";
|
2025-01-01 03:04:20 -05:00
|
|
|
|
|
|
|
|
const formatUrl = (port) => `http://${inject("backendHostname")}:${port}/stream.mjpg`;
|
|
|
|
|
const host = inject<string>("backendHost");
|
|
|
|
|
|
2025-01-07 08:45:39 -05:00
|
|
|
const activatingModule = ref(false);
|
2025-01-01 03:04:20 -05:00
|
|
|
const activateModule = (moduleUniqueName: string) => {
|
2025-01-07 08:45:39 -05:00
|
|
|
if (activatingModule.value) return;
|
|
|
|
|
activatingModule.value = true;
|
2025-01-01 03:04:20 -05:00
|
|
|
|
Standardize API (#1942)
## Description
closes #1941
Rewrite the API to use the payload method , and use records in the
``RequestHandler``. There's a couple places where this isn't the place,
that's where the front end is making a get request, and so a payload
doesn't make sense.
This is meant to encourage more static typing.
Additionally, fix some typos in params in ``CameraSettingsStore``
## 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_
- [x] If this PR changes behavior or adds a feature, user documentation
is updated
- [x] If this PR touches photon-serde, all messages have been
regenerated and hashes have not changed unexpectedly
- [x] If this PR touches configuration, this is backwards compatible
with settings back to v2024.3.1
- [x] If this PR touches pipeline settings or anything related to data
exchange, the frontend typing is updated
- [x] If this PR addresses a bug, a regression test for it is added
- [x] Everything changed got tested
---------
Co-authored-by: Matt Morley <matthew.morley.ca@gmail.com>
2025-05-04 00:15:32 -05:00
|
|
|
axios
|
|
|
|
|
.post("/utils/activateMatchedCamera", { cameraUniqueName: moduleUniqueName })
|
|
|
|
|
.then(() => {
|
|
|
|
|
useStateStore().showSnackbarMessage({
|
|
|
|
|
message: "Camera activated successfully",
|
|
|
|
|
color: "success"
|
|
|
|
|
});
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
if (error.response) {
|
|
|
|
|
useStateStore().showSnackbarMessage({
|
|
|
|
|
message: "The backend is unable to fulfil the request to activate 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(() => (activatingModule.value = false));
|
2025-01-01 03:04:20 -05:00
|
|
|
};
|
2025-01-07 08:45:39 -05:00
|
|
|
|
|
|
|
|
const assigningCamera = ref(false);
|
|
|
|
|
const assignCamera = (cameraInfo: PVCameraInfo) => {
|
|
|
|
|
if (assigningCamera.value) return;
|
|
|
|
|
assigningCamera.value = true;
|
2025-01-01 03:04:20 -05:00
|
|
|
|
Standardize API (#1942)
## Description
closes #1941
Rewrite the API to use the payload method , and use records in the
``RequestHandler``. There's a couple places where this isn't the place,
that's where the front end is making a get request, and so a payload
doesn't make sense.
This is meant to encourage more static typing.
Additionally, fix some typos in params in ``CameraSettingsStore``
## 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_
- [x] If this PR changes behavior or adds a feature, user documentation
is updated
- [x] If this PR touches photon-serde, all messages have been
regenerated and hashes have not changed unexpectedly
- [x] If this PR touches configuration, this is backwards compatible
with settings back to v2024.3.1
- [x] If this PR touches pipeline settings or anything related to data
exchange, the frontend typing is updated
- [x] If this PR addresses a bug, a regression test for it is added
- [x] Everything changed got tested
---------
Co-authored-by: Matt Morley <matthew.morley.ca@gmail.com>
2025-05-04 00:15:32 -05:00
|
|
|
const payload = {
|
|
|
|
|
cameraInfo: cameraInfo
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
axios
|
|
|
|
|
.post("/utils/assignUnmatchedCamera", payload)
|
|
|
|
|
.then(() => {
|
|
|
|
|
useStateStore().showSnackbarMessage({
|
|
|
|
|
message: "Unmatched camera assigned successfully",
|
|
|
|
|
color: "success"
|
|
|
|
|
});
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
if (error.response) {
|
|
|
|
|
useStateStore().showSnackbarMessage({
|
|
|
|
|
message: "The backend is unable to fulfil the request to assign this unmatched 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(() => (assigningCamera.value = false));
|
2025-01-01 03:04:20 -05:00
|
|
|
};
|
2025-01-07 08:45:39 -05:00
|
|
|
|
|
|
|
|
const deactivatingModule = ref(false);
|
|
|
|
|
const deactivateModule = (cameraUniqueName: string) => {
|
|
|
|
|
if (deactivatingModule.value) return;
|
|
|
|
|
deactivatingModule.value = true;
|
2025-01-01 03:04:20 -05:00
|
|
|
|
Standardize API (#1942)
## Description
closes #1941
Rewrite the API to use the payload method , and use records in the
``RequestHandler``. There's a couple places where this isn't the place,
that's where the front end is making a get request, and so a payload
doesn't make sense.
This is meant to encourage more static typing.
Additionally, fix some typos in params in ``CameraSettingsStore``
## 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_
- [x] If this PR changes behavior or adds a feature, user documentation
is updated
- [x] If this PR touches photon-serde, all messages have been
regenerated and hashes have not changed unexpectedly
- [x] If this PR touches configuration, this is backwards compatible
with settings back to v2024.3.1
- [x] If this PR touches pipeline settings or anything related to data
exchange, the frontend typing is updated
- [x] If this PR addresses a bug, a regression test for it is added
- [x] Everything changed got tested
---------
Co-authored-by: Matt Morley <matthew.morley.ca@gmail.com>
2025-05-04 00:15:32 -05:00
|
|
|
axios
|
|
|
|
|
.post("/utils/unassignCamera", { cameraUniqueName: cameraUniqueName })
|
|
|
|
|
.then(() => {
|
|
|
|
|
useStateStore().showSnackbarMessage({
|
|
|
|
|
message: "Camera deactivated successfully",
|
|
|
|
|
color: "success"
|
|
|
|
|
});
|
|
|
|
|
})
|
|
|
|
|
.catch((error) => {
|
|
|
|
|
if (error.response) {
|
|
|
|
|
useStateStore().showSnackbarMessage({
|
|
|
|
|
message: "The backend is unable to fulfil the request to deactivate 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(() => (deactivatingModule.value = false));
|
2025-01-01 03:04:20 -05:00
|
|
|
};
|
|
|
|
|
|
2025-01-07 08:45:39 -05:00
|
|
|
const deletingCamera = ref(false);
|
2025-01-01 03:04:20 -05:00
|
|
|
const deleteThisCamera = (cameraName: string) => {
|
2025-01-07 08:45:39 -05:00
|
|
|
if (deletingCamera.value) return;
|
|
|
|
|
deletingCamera.value = true;
|
2025-01-01 03:04:20 -05:00
|
|
|
const payload = {
|
|
|
|
|
cameraUniqueName: cameraName
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
axios
|
|
|
|
|
.post("/utils/nukeOneCamera", payload)
|
|
|
|
|
.then(() => {
|
|
|
|
|
useStateStore().showSnackbarMessage({
|
2025-01-07 08:45:39 -05:00
|
|
|
message: "Camera deleted successfully",
|
2025-01-01 03:04:20 -05:00
|
|
|
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"
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-01-07 08:45:39 -05:00
|
|
|
})
|
|
|
|
|
.finally(() => {
|
|
|
|
|
setCameraDeleting(null);
|
|
|
|
|
deletingCamera.value = false;
|
2025-01-01 03:04:20 -05:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2025-01-07 08:45:39 -05:00
|
|
|
const camerasMatch = (camera1: PVCameraInfo, camera2: PVCameraInfo) => {
|
|
|
|
|
if (camera1.PVUsbCameraInfo && camera2.PVUsbCameraInfo)
|
|
|
|
|
return (
|
|
|
|
|
camera1.PVUsbCameraInfo.name === camera2.PVUsbCameraInfo.name &&
|
|
|
|
|
camera1.PVUsbCameraInfo.vendorId === camera2.PVUsbCameraInfo.vendorId &&
|
|
|
|
|
camera1.PVUsbCameraInfo.productId === camera2.PVUsbCameraInfo.productId &&
|
|
|
|
|
camera1.PVUsbCameraInfo.uniquePath === camera2.PVUsbCameraInfo.uniquePath
|
|
|
|
|
);
|
|
|
|
|
else if (camera1.PVCSICameraInfo && camera2.PVCSICameraInfo)
|
|
|
|
|
return (
|
|
|
|
|
camera1.PVCSICameraInfo.uniquePath === camera2.PVCSICameraInfo.uniquePath &&
|
|
|
|
|
camera1.PVCSICameraInfo.baseName === camera2.PVCSICameraInfo.baseName
|
|
|
|
|
);
|
|
|
|
|
else if (camera1.PVFileCameraInfo && camera2.PVFileCameraInfo)
|
|
|
|
|
return (
|
|
|
|
|
camera1.PVFileCameraInfo.uniquePath === camera2.PVFileCameraInfo.uniquePath &&
|
|
|
|
|
camera1.PVFileCameraInfo.name === camera2.PVFileCameraInfo.name
|
|
|
|
|
);
|
|
|
|
|
else return false;
|
|
|
|
|
};
|
|
|
|
|
|
2025-01-14 02:30:25 -05:00
|
|
|
const cameraInfoFor = (camera: PVCameraInfo | null): PVUsbCameraInfo | PVCSICameraInfo | PVFileCameraInfo | any => {
|
|
|
|
|
if (!camera) return null;
|
2025-01-01 03:04:20 -05:00
|
|
|
if (camera.PVUsbCameraInfo) {
|
|
|
|
|
return camera.PVUsbCameraInfo;
|
|
|
|
|
}
|
|
|
|
|
if (camera.PVCSICameraInfo) {
|
|
|
|
|
return camera.PVCSICameraInfo;
|
|
|
|
|
}
|
|
|
|
|
if (camera.PVFileCameraInfo) {
|
|
|
|
|
return camera.PVFileCameraInfo;
|
|
|
|
|
}
|
|
|
|
|
return {};
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Find the PVCameraInfo currently occupying the same uniquepath as the the given module
|
|
|
|
|
*/
|
|
|
|
|
const getMatchedDevice = (info: PVCameraInfo | undefined): PVCameraInfo => {
|
|
|
|
|
if (!info) {
|
|
|
|
|
return {
|
2025-01-14 02:30:25 -05:00
|
|
|
PVFileCameraInfo: undefined,
|
2025-01-01 03:04:20 -05:00
|
|
|
PVCSICameraInfo: undefined,
|
|
|
|
|
PVUsbCameraInfo: undefined
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
return (
|
|
|
|
|
useStateStore().vsmState.allConnectedCameras.find(
|
2025-01-14 02:30:25 -05:00
|
|
|
(it) => cameraInfoFor(it).uniquePath === cameraInfoFor(info).uniquePath
|
2025-01-01 03:04:20 -05:00
|
|
|
) || {
|
2025-01-14 02:30:25 -05:00
|
|
|
PVFileCameraInfo: undefined,
|
2025-01-01 03:04:20 -05:00
|
|
|
PVCSICameraInfo: undefined,
|
|
|
|
|
PVUsbCameraInfo: undefined
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2025-01-14 02:30:25 -05:00
|
|
|
const cameraCononected = (uniquePath: string): boolean => {
|
|
|
|
|
return (
|
|
|
|
|
useStateStore().vsmState.allConnectedCameras.find((it) => cameraInfoFor(it).uniquePath === uniquePath) !== undefined
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
2025-01-01 03:04:20 -05:00
|
|
|
const unmatchedCameras = computed(() => {
|
2025-01-14 02:30:25 -05:00
|
|
|
const activeVmPaths = Object.values(useCameraSettingsStore().cameras).map(
|
|
|
|
|
(it) => cameraInfoFor(it.matchedCameraInfo).uniquePath
|
2025-01-03 18:50:25 -05:00
|
|
|
);
|
2025-01-14 02:30:25 -05:00
|
|
|
const disabledVmPaths = useStateStore().vsmState.disabledConfigs.map(
|
|
|
|
|
(it) => cameraInfoFor(it.matchedCameraInfo).uniquePath
|
2025-01-01 03:04:20 -05:00
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return useStateStore().vsmState.allConnectedCameras.filter(
|
2025-01-14 02:30:25 -05:00
|
|
|
(it) =>
|
|
|
|
|
!activeVmPaths.includes(cameraInfoFor(it).uniquePath) && !disabledVmPaths.includes(cameraInfoFor(it).uniquePath)
|
2025-01-01 03:04:20 -05:00
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const activeVisionModules = computed(() =>
|
2025-01-14 02:30:25 -05:00
|
|
|
Object.values(useCameraSettingsStore().cameras)
|
|
|
|
|
// Ignore placeholder camera
|
|
|
|
|
.filter((camera) => JSON.stringify(camera) !== JSON.stringify(PlaceholderCameraSettings))
|
|
|
|
|
// Display connected cameras first
|
|
|
|
|
.sort(
|
|
|
|
|
(first, second) =>
|
|
|
|
|
(cameraCononected(cameraInfoFor(second.matchedCameraInfo).uniquePath) ? 1 : 0) -
|
|
|
|
|
(cameraCononected(cameraInfoFor(first.matchedCameraInfo).uniquePath) ? 1 : 0)
|
|
|
|
|
)
|
2025-01-01 03:04:20 -05:00
|
|
|
);
|
2025-01-14 02:30:25 -05:00
|
|
|
|
2025-01-01 03:04:20 -05:00
|
|
|
const disabledVisionModules = computed(() => useStateStore().vsmState.disabledConfigs);
|
|
|
|
|
|
|
|
|
|
const viewingDetails = ref(false);
|
2025-01-14 02:30:25 -05:00
|
|
|
const viewingCamera = ref<[PVCameraInfo | null, boolean | null]>([null, null]);
|
|
|
|
|
const setCameraView = (camera: PVCameraInfo | null, isConnected: boolean | null) => {
|
|
|
|
|
viewingDetails.value = camera !== null && isConnected !== null;
|
|
|
|
|
viewingCamera.value = [camera, isConnected];
|
2025-01-01 03:04:20 -05:00
|
|
|
};
|
2025-01-07 08:45:39 -05:00
|
|
|
|
|
|
|
|
const viewingDeleteCamera = ref(false);
|
|
|
|
|
const cameraToDelete = ref<UiCameraConfiguration | WebsocketCameraSettingsUpdate | null>(null);
|
|
|
|
|
const setCameraDeleting = (camera: UiCameraConfiguration | WebsocketCameraSettingsUpdate | null) => {
|
|
|
|
|
yesDeleteMySettingsText.value = "";
|
|
|
|
|
viewingDeleteCamera.value = camera !== null;
|
|
|
|
|
cameraToDelete.value = camera;
|
|
|
|
|
};
|
|
|
|
|
const yesDeleteMySettingsText = ref("");
|
|
|
|
|
const exportSettings = ref();
|
|
|
|
|
const openExportSettingsPrompt = () => {
|
|
|
|
|
exportSettings.value.click();
|
|
|
|
|
};
|
2025-01-01 03:04:20 -05:00
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<template>
|
2025-05-06 18:21:41 -04:00
|
|
|
<div class="pa-3">
|
2025-01-01 03:04:20 -05:00
|
|
|
<v-row>
|
|
|
|
|
<!-- Active modules -->
|
2025-01-07 08:45:39 -05:00
|
|
|
<v-col
|
|
|
|
|
v-for="(module, index) in activeVisionModules"
|
|
|
|
|
:key="`enabled-${module.uniqueName}`"
|
|
|
|
|
cols="12"
|
|
|
|
|
sm="6"
|
|
|
|
|
lg="4"
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
class="pr-0"
|
2025-01-07 08:45:39 -05:00
|
|
|
>
|
2025-05-06 18:21:41 -04:00
|
|
|
<v-card color="primary">
|
2025-01-07 08:45:39 -05:00
|
|
|
<v-card-title>{{ cameraInfoFor(module.matchedCameraInfo).name }}</v-card-title>
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-card-subtitle v-if="!cameraCononected(cameraInfoFor(module.matchedCameraInfo).uniquePath)"
|
2025-01-14 02:30:25 -05:00
|
|
|
>Status: <span class="inactive-status">Disconnected</span></v-card-subtitle
|
|
|
|
|
>
|
|
|
|
|
<v-card-subtitle
|
|
|
|
|
v-else-if="
|
|
|
|
|
cameraCononected(cameraInfoFor(module.matchedCameraInfo).uniquePath) &&
|
|
|
|
|
camerasMatch(getMatchedDevice(module.matchedCameraInfo), module.matchedCameraInfo)
|
|
|
|
|
"
|
2025-01-01 03:04:20 -05:00
|
|
|
>Status: <span class="active-status">Active</span></v-card-subtitle
|
|
|
|
|
>
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-card-subtitle v-else>Status: <span class="mismatch-status">Mismatch</span></v-card-subtitle>
|
|
|
|
|
<v-card-text class="pt-3">
|
2025-05-06 18:21:41 -04:00
|
|
|
<v-table density="compact">
|
2025-01-01 03:04:20 -05:00
|
|
|
<tbody>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Streams:</td>
|
|
|
|
|
<td>
|
2025-01-14 02:30:25 -05:00
|
|
|
<a :href="formatUrl(module.stream.inputPort)" target="_blank" class="stream-link"> Input </a>
|
2025-01-01 03:04:20 -05:00
|
|
|
/
|
2025-01-14 02:30:25 -05:00
|
|
|
<a :href="formatUrl(module.stream.outputPort)" target="_blank" class="stream-link"> Output </a>
|
2025-01-01 03:04:20 -05:00
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Pipelines</td>
|
|
|
|
|
<td>{{ module.pipelineNicknames.join(", ") }}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Calibrations</td>
|
|
|
|
|
<td>
|
|
|
|
|
{{
|
|
|
|
|
module.completeCalibrations.map((it) => getResolutionString(it.resolution)).join(", ") ||
|
|
|
|
|
"Not calibrated"
|
|
|
|
|
}}
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
2025-01-14 02:30:25 -05:00
|
|
|
<tr
|
|
|
|
|
v-if="
|
|
|
|
|
cameraCononected(cameraInfoFor(module.matchedCameraInfo).uniquePath) &&
|
|
|
|
|
useStateStore().backendResults[module.uniqueName]
|
|
|
|
|
"
|
|
|
|
|
>
|
|
|
|
|
<td style="width: 50%">Frames Processed</td>
|
2025-01-01 03:04:20 -05:00
|
|
|
<td>
|
2025-01-03 18:50:25 -05:00
|
|
|
{{ useStateStore().backendResults[module.uniqueName].sequenceID }} ({{
|
|
|
|
|
useStateStore().backendResults[module.uniqueName].fps
|
2025-01-01 03:04:20 -05:00
|
|
|
}}
|
|
|
|
|
FPS)
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
2025-05-06 18:21:41 -04:00
|
|
|
</v-table>
|
2025-01-07 08:45:39 -05:00
|
|
|
<div
|
2025-01-14 02:30:25 -05:00
|
|
|
v-if="cameraCononected(cameraInfoFor(module.matchedCameraInfo).uniquePath)"
|
2025-01-07 08:45:39 -05:00
|
|
|
:id="`stream-container-${index}`"
|
2025-01-14 02:30:25 -05:00
|
|
|
class="d-flex flex-column justify-center align-center mt-3"
|
2025-01-07 08:45:39 -05:00
|
|
|
style="height: 250px"
|
|
|
|
|
>
|
|
|
|
|
<photon-camera-stream
|
|
|
|
|
:id="`output-camera-stream-${index}`"
|
|
|
|
|
:camera-settings="module"
|
|
|
|
|
stream-type="Processed"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2025-01-01 03:04:20 -05:00
|
|
|
</v-card-text>
|
|
|
|
|
<v-card-text class="pt-0">
|
|
|
|
|
<v-row>
|
|
|
|
|
<v-col cols="12" md="4" class="pr-md-0 pb-0 pb-md-3">
|
2025-01-14 02:30:25 -05:00
|
|
|
<v-btn
|
|
|
|
|
color="secondary"
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
@click="
|
|
|
|
|
setCameraView(
|
|
|
|
|
module.matchedCameraInfo,
|
|
|
|
|
cameraCononected(cameraInfoFor(module.matchedCameraInfo).uniquePath)
|
|
|
|
|
)
|
|
|
|
|
"
|
|
|
|
|
>
|
2025-01-01 03:04:20 -05:00
|
|
|
<span>Details</span>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-col>
|
|
|
|
|
<v-col cols="6" md="5" class="pr-0">
|
|
|
|
|
<v-btn
|
2025-05-06 18:21:41 -04:00
|
|
|
class="text-black"
|
2025-01-01 03:04:20 -05:00
|
|
|
color="accent"
|
|
|
|
|
style="width: 100%"
|
2025-01-07 08:45:39 -05:00
|
|
|
:loading="deactivatingModule"
|
|
|
|
|
@click="deactivateModule(module.uniqueName)"
|
2025-01-01 03:04:20 -05:00
|
|
|
>
|
|
|
|
|
Deactivate
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-col>
|
|
|
|
|
<v-col cols="6" md="3">
|
2025-01-07 08:45:39 -05:00
|
|
|
<v-btn class="pa-0" color="error" style="width: 100%" @click="setCameraDeleting(module)">
|
2025-01-01 03:04:20 -05:00
|
|
|
<v-icon>mdi-trash-can-outline</v-icon>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-col>
|
|
|
|
|
|
|
|
|
|
<!-- Disabled modules -->
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-col
|
|
|
|
|
v-for="module in disabledVisionModules"
|
|
|
|
|
:key="`disabled-${module.uniqueName}`"
|
|
|
|
|
cols="12"
|
|
|
|
|
sm="6"
|
|
|
|
|
lg="4"
|
|
|
|
|
class="pr-0"
|
|
|
|
|
>
|
|
|
|
|
<v-card class="pr-0" color="primary">
|
2025-01-01 03:04:20 -05:00
|
|
|
<v-card-title>{{ module.nickname }}</v-card-title>
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-card-subtitle>Status: <span class="inactive-status">Deactivated</span></v-card-subtitle>
|
|
|
|
|
<v-card-text class="pt-3">
|
2025-05-06 18:21:41 -04:00
|
|
|
<v-table density="compact">
|
2025-01-01 03:04:20 -05:00
|
|
|
<tbody>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Name</td>
|
|
|
|
|
<td>
|
|
|
|
|
{{ module.cameraQuirks.baseName }}
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Pipelines</td>
|
|
|
|
|
<td>{{ module.pipelineNicknames.join(", ") }}</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Connected</td>
|
2025-01-14 02:30:25 -05:00
|
|
|
<td>{{ cameraCononected(cameraInfoFor(module.matchedCameraInfo).uniquePath) }}</td>
|
2025-01-01 03:04:20 -05:00
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td>Calibrations</td>
|
|
|
|
|
<td>
|
|
|
|
|
{{
|
|
|
|
|
module.calibrations.map((it2) => getResolutionString(it2.resolution)).join(", ") ||
|
|
|
|
|
"Not calibrated"
|
|
|
|
|
}}
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
2025-05-06 18:21:41 -04:00
|
|
|
</v-table>
|
2025-01-01 03:04:20 -05:00
|
|
|
</v-card-text>
|
|
|
|
|
<v-card-text class="pt-0">
|
|
|
|
|
<v-row>
|
|
|
|
|
<v-col cols="12" md="4" class="pr-md-0 pb-0 pb-md-3">
|
2025-01-14 02:30:25 -05:00
|
|
|
<v-btn
|
|
|
|
|
color="secondary"
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
@click="
|
|
|
|
|
setCameraView(
|
|
|
|
|
module.matchedCameraInfo,
|
|
|
|
|
cameraCononected(cameraInfoFor(module.matchedCameraInfo).uniquePath)
|
|
|
|
|
)
|
|
|
|
|
"
|
|
|
|
|
>
|
2025-01-01 03:04:20 -05:00
|
|
|
<span>Details</span>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-col>
|
|
|
|
|
<v-col cols="6" md="5" class="pr-0">
|
|
|
|
|
<v-btn
|
2025-05-06 18:21:41 -04:00
|
|
|
class="text-black"
|
2025-01-01 03:04:20 -05:00
|
|
|
color="accent"
|
|
|
|
|
style="width: 100%"
|
2025-01-07 08:45:39 -05:00
|
|
|
:loading="activatingModule"
|
2025-01-03 08:29:18 -06:00
|
|
|
@click="activateModule(module.uniqueName)"
|
2025-01-01 03:04:20 -05:00
|
|
|
>
|
|
|
|
|
Activate
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-col>
|
|
|
|
|
<v-col cols="6" md="3">
|
2025-01-07 08:45:39 -05:00
|
|
|
<v-btn class="pa-0" color="error" style="width: 100%" @click="setCameraDeleting(module)">
|
2025-01-01 03:04:20 -05:00
|
|
|
<v-icon>mdi-trash-can-outline</v-icon>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-col>
|
|
|
|
|
|
|
|
|
|
<!-- Unassigned cameras -->
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-col v-for="(camera, index) in unmatchedCameras" :key="index" cols="12" sm="6" lg="4" class="pr-0">
|
|
|
|
|
<v-card class="pr-0" color="primary">
|
|
|
|
|
<v-card-title>
|
2025-01-01 03:04:20 -05:00
|
|
|
<span v-if="camera.PVUsbCameraInfo">USB Camera:</span>
|
|
|
|
|
<span v-else-if="camera.PVCSICameraInfo">CSI Camera:</span>
|
|
|
|
|
<span v-else-if="camera.PVFileCameraInfo">File Camera:</span>
|
|
|
|
|
<span v-else>Unknown Camera:</span>
|
|
|
|
|
<span>{{ cameraInfoFor(camera)?.name ?? cameraInfoFor(camera)?.baseName }}</span>
|
|
|
|
|
</v-card-title>
|
|
|
|
|
<v-card-subtitle>Status: Unassigned</v-card-subtitle>
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-card-text class="pt-3">
|
2025-01-01 03:04:20 -05:00
|
|
|
<span style="word-break: break-all">{{ cameraInfoFor(camera)?.path }}</span>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
<v-card-text class="pt-0">
|
|
|
|
|
<v-row>
|
|
|
|
|
<v-col cols="6" class="pr-0">
|
2025-01-14 02:30:25 -05:00
|
|
|
<v-btn color="secondary" style="width: 100%" @click="setCameraView(camera, false)">
|
2025-01-01 03:04:20 -05:00
|
|
|
<span>Details</span>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-col>
|
|
|
|
|
<v-col cols="6">
|
2025-01-07 08:45:39 -05:00
|
|
|
<v-btn
|
2025-05-06 18:21:41 -04:00
|
|
|
class="text-black"
|
2025-01-07 08:45:39 -05:00
|
|
|
color="accent"
|
|
|
|
|
style="width: 100%"
|
|
|
|
|
:loading="assigningCamera"
|
|
|
|
|
@click="assignCamera(camera)"
|
|
|
|
|
>
|
2025-01-01 03:04:20 -05:00
|
|
|
Activate
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-col>
|
|
|
|
|
|
|
|
|
|
<!-- Info card -->
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-col cols="12" sm="6" lg="4" class="pr-0">
|
2025-01-01 03:04:20 -05:00
|
|
|
<v-card
|
|
|
|
|
dark
|
|
|
|
|
flat
|
|
|
|
|
class="pl-6 pr-6 d-flex flex-column justify-center"
|
|
|
|
|
style="background-color: transparent; height: 100%"
|
|
|
|
|
>
|
|
|
|
|
<v-card-text class="d-flex flex-column align-center justify-center">
|
|
|
|
|
<v-icon size="64" color="primary">mdi-plus</v-icon>
|
|
|
|
|
</v-card-text>
|
|
|
|
|
<v-card-title>Additional plugged in cameras will display here!</v-card-title>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
|
|
|
|
|
<!-- Camera details modal -->
|
2025-01-07 08:45:39 -05:00
|
|
|
<v-dialog v-model="viewingDetails" max-width="800">
|
2025-05-06 18:21:41 -04:00
|
|
|
<v-card v-if="viewingCamera[0] !== null" flat color="primary">
|
2025-01-01 03:04:20 -05:00
|
|
|
<v-card-title class="d-flex justify-space-between">
|
2025-01-14 02:30:25 -05:00
|
|
|
<span>{{ cameraInfoFor(viewingCamera[0])?.name ?? cameraInfoFor(viewingCamera[0])?.baseName }}</span>
|
2025-05-06 18:21:41 -04:00
|
|
|
<v-btn variant="text" @click="setCameraView(null, null)">
|
2025-01-01 03:04:20 -05:00
|
|
|
<v-icon>mdi-close-thick</v-icon>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-card-title>
|
2025-01-14 02:30:25 -05:00
|
|
|
<v-card-text v-if="!viewingCamera[1]">
|
|
|
|
|
<PvCameraInfoCard :camera="viewingCamera[0]" />
|
|
|
|
|
</v-card-text>
|
|
|
|
|
<v-card-text v-else-if="!camerasMatch(getMatchedDevice(viewingCamera[0]), viewingCamera[0])">
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-banner rounded bg-color="error" text-color="white" icon="mdi-information-outline" class="mb-3">
|
2025-01-07 08:45:39 -05:00
|
|
|
It looks like a different camera may have been connected to this device! Compare the following information
|
|
|
|
|
carefully.
|
|
|
|
|
</v-banner>
|
2025-01-14 02:30:25 -05:00
|
|
|
<PvCameraMatchCard :saved="viewingCamera[0]" :current="getMatchedDevice(viewingCamera[0])" />
|
2025-01-07 08:45:39 -05:00
|
|
|
</v-card-text>
|
|
|
|
|
<v-card-text v-else>
|
2025-01-14 02:30:25 -05:00
|
|
|
<PvCameraInfoCard :camera="getMatchedDevice(viewingCamera[0])" />
|
2025-01-07 08:45:39 -05:00
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-dialog>
|
|
|
|
|
|
|
|
|
|
<!-- Camera delete modal -->
|
2025-05-06 18:21:41 -04:00
|
|
|
<v-dialog v-model="viewingDeleteCamera" width="800">
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-card v-if="cameraToDelete !== null" class="dialog-container" color="primary" flat>
|
2025-01-07 08:45:39 -05:00
|
|
|
<v-card-title> Delete {{ cameraToDelete.nickname }}? </v-card-title>
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-card-text class="pb-10px">
|
|
|
|
|
<v-row class="align-center">
|
2025-01-07 08:45:39 -05:00
|
|
|
<v-col cols="12" md="6">
|
2025-05-06 18:21:41 -04:00
|
|
|
<span class="text-white"> This will delete ALL OF YOUR SETTINGS and restart PhotonVision. </span>
|
2025-01-07 08:45:39 -05:00
|
|
|
</v-col>
|
|
|
|
|
<v-col cols="12" md="6">
|
|
|
|
|
<v-btn color="secondary" block @click="openExportSettingsPrompt">
|
2025-05-06 18:21:41 -04:00
|
|
|
<v-icon start class="open-icon"> mdi-export </v-icon>
|
2025-01-07 08:45:39 -05:00
|
|
|
<span class="open-label">Backup Settings</span>
|
|
|
|
|
<a
|
|
|
|
|
ref="exportSettings"
|
|
|
|
|
style="color: black; text-decoration: none; display: none"
|
|
|
|
|
:href="`http://${host}/api/settings/photonvision_config.zip`"
|
|
|
|
|
download="photonvision-settings.zip"
|
|
|
|
|
target="_blank"
|
|
|
|
|
/>
|
|
|
|
|
</v-btn>
|
|
|
|
|
</v-col>
|
|
|
|
|
</v-row>
|
|
|
|
|
</v-card-text>
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-card-text class="pt-0 pb-0">
|
2025-01-07 08:45:39 -05:00
|
|
|
<pv-input
|
|
|
|
|
v-model="yesDeleteMySettingsText"
|
|
|
|
|
:label="'Type "' + cameraToDelete.nickname + '":'"
|
|
|
|
|
:label-cols="6"
|
|
|
|
|
:input-cols="6"
|
|
|
|
|
/>
|
|
|
|
|
</v-card-text>
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
<v-card-text class="pt-10px">
|
2025-01-07 08:45:39 -05:00
|
|
|
<v-btn
|
|
|
|
|
block
|
|
|
|
|
color="error"
|
|
|
|
|
:disabled="yesDeleteMySettingsText.toLowerCase() !== cameraToDelete.nickname.toLowerCase()"
|
|
|
|
|
:loading="deletingCamera"
|
|
|
|
|
@click="deleteThisCamera(cameraToDelete.uniqueName)"
|
2025-01-01 03:04:20 -05:00
|
|
|
>
|
2025-05-06 18:21:41 -04:00
|
|
|
<v-icon start class="open-icon"> mdi-trash-can-outline </v-icon>
|
2025-01-07 08:45:39 -05:00
|
|
|
<span class="open-label">DELETE (UNRECOVERABLE)</span>
|
|
|
|
|
</v-btn>
|
2025-01-01 03:04:20 -05:00
|
|
|
</v-card-text>
|
|
|
|
|
</v-card>
|
|
|
|
|
</v-dialog>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
td {
|
|
|
|
|
padding: 0 !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.v-card-subtitle {
|
|
|
|
|
padding-top: 0px !important;
|
|
|
|
|
padding-bottom: 8px !important;
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-06 18:21:41 -04:00
|
|
|
.v-card-title {
|
Clean up spacing and other things in various parts of the UI (#1972)
## Description
After the Vue 3 upgrade, the spacing for various UI elements was left
inconsistent in many places. Dialogs were hit especially hard and had
some very inconsistent spacing. Additionally, the 24 pixels of padding
around all cards was noted as a waste of space and unnecessary, so it
has been shrunk down to 20 pixels to make the UI a tiny bit more compact
and to make it visually closer to some parts of the UI that have 16
pixels of padding (the camera views are the most notable example).
Padding between input elements has also been reduced to 20 pixels (this
required some hackery to get consistent sizes on input elements, since
switches and sliders have different heights.)
Some other minor UI tweaks were made, such as removing the divider
between dialog contents and dialog buttons because it visually looks
better, shrinking the banner padding so it doesn't displace as much
content, making the banner background one uniform color instead of a
highlight around the icon, fixing the targets tab so that the columns
stop shifting around when the values change, preserving newlines in the
log view, cleaning up the object detection UI, and making the import
dialogs have consistently inset input elements.
Old dashboard:

New dashboard:

Old Camera tab:

New Camera tab:

Old Calibration Info:

New Calibration Info:

Old Log Viewer:

New Log Viewer:

Old Pipeline Creation Dialog:

New Pipeline Creation Dialog:

Old Factory Reset:

New Factory Reset:

Old Pipeline Change:

New Pipeline Change:

Old Import Dialog:

New Import Dialog:

## 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 v2024.3.1
- [ ] 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
2025-07-12 00:02:23 -04:00
|
|
|
padding-bottom: 0 !important;
|
2025-05-06 18:21:41 -04:00
|
|
|
text-wrap-mode: wrap !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.v-table {
|
2025-01-01 03:04:20 -05:00
|
|
|
background-color: #006492 !important;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.active-status {
|
|
|
|
|
color: rgb(14, 240, 14);
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.inactive-status {
|
|
|
|
|
color: red;
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a:hover {
|
|
|
|
|
color: pink;
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
a:active,
|
2025-01-07 08:45:39 -05:00
|
|
|
.stream-link,
|
2025-01-01 03:04:20 -05:00
|
|
|
.mismatch-status {
|
|
|
|
|
color: yellow;
|
|
|
|
|
background-color: transparent;
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
}
|
|
|
|
|
</style>
|