Files
PhotonVision/photon-client/src/components/app/photon-sidebar.vue
Graham bec8092660 Vue 3 Upgrade (#1900)
## Description

Upgrades to Vue 3 and necessary associated dependencies. Also fixes some
issues with the layout and adds validation for object detection models.

Closes #885, closes #1943, closes #1449.
## 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

---------

Co-authored-by: Matt M <matthew.morley.ca@gmail.com>
Co-authored-by: Gold856 <117957790+Gold856@users.noreply.github.com>
Co-authored-by: samfreund <techguy763@gmail.com>
2025-05-06 18:21:41 -04:00

144 lines
4.9 KiB
Vue

<script setup lang="ts">
import { computed } from "vue";
import { useSettingsStore } from "@/stores/settings/GeneralSettingsStore";
import { useStateStore } from "@/stores/StateStore";
import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";
import { PlaceholderCameraSettings } from "@/types/SettingTypes";
import { useRoute } from "vue-router";
import { useDisplay } from "vuetify";
const compact = computed<boolean>({
get: () => {
return useStateStore().sidebarFolded;
},
set: (val) => {
useStateStore().setSidebarFolded(val);
}
});
const { mdAndUp } = useDisplay();
const renderCompact = computed<boolean>(() => compact.value || !mdAndUp.value);
const needsCamerasConfigured = computed<boolean>(() => {
return (
Object.values(useCameraSettingsStore().cameras).length === 0 ||
useCameraSettingsStore().cameras["PlaceHolder Name"] === PlaceholderCameraSettings
);
});
</script>
<template>
<v-navigation-drawer permanent :rail="renderCompact" color="primary">
<v-list nav>
<!-- List item for the heading; note that there are some tricks in setting padding and image width make things look right -->
<v-list-item :class="renderCompact ? 'pr-0 pl-0' : ''" style="display: flex; justify-content: center">
<template #prepend>
<img v-if="!renderCompact" class="logo" src="@/assets/images/logoLarge.svg" alt="large logo" />
<img v-else class="logo" src="@/assets/images/logoSmall.svg" alt="small logo" />
</template>
</v-list-item>
<v-list-item link to="/dashboard" prepend-icon="mdi-view-dashboard">
<v-list-item-title>Dashboard</v-list-item-title>
</v-list-item>
<v-list-item link to="/settings" prepend-icon="mdi-cog">
<v-list-item-title>Settings</v-list-item-title>
</v-list-item>
<v-list-item ref="camerasTabOpener" link to="/cameras" prepend-icon="mdi-camera">
<v-list-item-title>Camera</v-list-item-title>
</v-list-item>
<v-list-item
link
to="/cameraConfigs"
:class="{ cameraicon: needsCamerasConfigured && useRoute().path !== '/cameraConfigs' }"
>
<template #prepend>
<v-icon :class="{ 'text-red': needsCamerasConfigured }">mdi-swap-horizontal-bold</v-icon>
</template>
<v-list-item-title :class="{ 'text-red': needsCamerasConfigured }">Camera Matching</v-list-item-title>
</v-list-item>
<v-list-item link to="/docs" prepend-icon="mdi-bookshelf">
<v-list-item-title>Documentation</v-list-item-title>
</v-list-item>
</v-list>
<template #append>
<v-list nav>
<v-list-item
v-if="mdAndUp"
link
:prepend-icon="`mdi-chevron-${compact || !mdAndUp ? 'right' : 'left'}`"
@click="() => (compact = !compact)"
>
<v-list-item-title>Compact Mode</v-list-item-title>
</v-list-item>
<v-list-item
:prepend-icon="
useSettingsStore().network.runNTServer
? 'mdi-server'
: useStateStore().ntConnectionStatus.connected
? 'mdi-robot'
: 'mdi-robot-off'
"
>
<v-list-item-title v-if="useSettingsStore().network.runNTServer" v-show="!renderCompact" class="text-wrap">
NetworkTables server running for
<span class="text-accent">{{ useStateStore().ntConnectionStatus.clients || 0 }}</span> clients
</v-list-item-title>
<v-list-item-title
v-else-if="useStateStore().ntConnectionStatus.connected && useStateStore().backendConnected"
v-show="!renderCompact"
class="text-wrap"
style="flex-direction: column; display: flex"
>
NetworkTables Server Connected!
<span class="text-accent">
{{ useStateStore().ntConnectionStatus.address }}
</span>
</v-list-item-title>
<v-list-item-title
v-else
v-show="!renderCompact"
class="text-wrap"
style="flex-direction: column; display: flex"
>
Not connected to NetworkTables Server!
</v-list-item-title>
</v-list-item>
<v-list-item :prepend-icon="useStateStore().backendConnected ? 'mdi-server-network' : 'mdi-server-network-off'">
<v-list-item-title v-show="!renderCompact" class="text-wrap">
{{ useStateStore().backendConnected ? "Backend connected" : "Trying to connect to backend" }}
</v-list-item-title>
</v-list-item>
</v-list>
</template>
</v-navigation-drawer>
</template>
<style scoped>
.v-list-item-title {
font-size: 1rem !important;
line-height: 1.2rem !important;
}
.logo {
width: 100%;
height: 70px;
object-fit: contain;
}
.cameraicon {
animation: pulse 2s infinite;
}
@keyframes pulse {
0%,
100% {
transform: scale(0.95);
}
50% {
transform: scale(1.05);
}
}
</style>