mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-27 02:01:40 +00:00
UI Redesign (#22)
* Rework UI into a new, responsive layout * Send two streams (only one is currently downscaled)
This commit is contained in:
committed by
GitHub
parent
aed92e7132
commit
8b46ad1cab
@@ -3,7 +3,6 @@
|
||||
id="CameraStream"
|
||||
:style="styleObject"
|
||||
:src="address"
|
||||
crossorigin="Anonymous"
|
||||
alt=""
|
||||
@click="e => $emit('click', e)"
|
||||
>
|
||||
@@ -13,19 +12,27 @@
|
||||
export default {
|
||||
name: "CvImage",
|
||||
// eslint-disable-next-line vue/require-prop-types
|
||||
props: ['address', 'scale'],
|
||||
props: ['address', 'scale', 'maxHeight', 'maxHeightMd', 'maxHeightXl'],
|
||||
data: () => {
|
||||
return {}
|
||||
},
|
||||
computed: {
|
||||
styleObject: {
|
||||
get() {
|
||||
return {
|
||||
width: `${this.scale}%`,
|
||||
height: `${this.scale}%`,
|
||||
display: 'block',
|
||||
margin: 'auto'
|
||||
let ret = {
|
||||
"object-fit": "contain",
|
||||
"max-height": this.maxHeight,
|
||||
width: `${this.scale}%`,
|
||||
height: `${this.scale}%`,
|
||||
};
|
||||
|
||||
if (this.$vuetify.breakpoint.xl) {
|
||||
ret["max-height"] = this.maxHeightXl;
|
||||
} else if (this.$vuetify.breakpoint.mdAndUp) {
|
||||
ret["max-height"] = this.maxHeightMd;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
dense
|
||||
align="center"
|
||||
>
|
||||
<v-col :cols="3">
|
||||
<span>{{ name }}</span>
|
||||
<v-col cols="4">
|
||||
<span class="ml-2">{{ name }}</span>
|
||||
</v-col>
|
||||
<v-col :cols="9">
|
||||
<v-col cols="8">
|
||||
<v-text-field
|
||||
v-model="localValue"
|
||||
dark
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row dense align="center">
|
||||
<v-row
|
||||
dense
|
||||
align="center"
|
||||
>
|
||||
<v-col :cols="2">
|
||||
<span>{{ name }}</span>
|
||||
</v-col>
|
||||
|
||||
@@ -4,18 +4,18 @@
|
||||
dense
|
||||
align="center"
|
||||
>
|
||||
<v-col :cols="3">
|
||||
<v-col :cols="12 - (selectCols || 9)">
|
||||
<span>{{ name }}</span>
|
||||
</v-col>
|
||||
<v-col :cols="9">
|
||||
<v-col :cols="selectCols || 9">
|
||||
<v-select
|
||||
v-model="localValue"
|
||||
:items="indexList"
|
||||
item-text="name"
|
||||
item-value="index"
|
||||
dark
|
||||
color="#fcf6de"
|
||||
item-color="blue"
|
||||
color="accent"
|
||||
item-color="secondary"
|
||||
:disabled="disabled"
|
||||
@change="$emit('rollback', localValue)"
|
||||
/>
|
||||
@@ -28,7 +28,7 @@
|
||||
export default {
|
||||
name: 'Select',
|
||||
// eslint-disable-next-line vue/require-prop-types
|
||||
props: ['list', 'name', 'value', 'disabled'],
|
||||
props: ['list', 'name', 'value', 'disabled', 'selectCols'],
|
||||
data() {
|
||||
return {}
|
||||
},
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row dense align="center">
|
||||
<v-col :cols="2">
|
||||
<v-row
|
||||
dense
|
||||
align="center"
|
||||
>
|
||||
<v-col :cols="12 - (sliderCols || 8)">
|
||||
<span>{{ name }}</span>
|
||||
</v-col>
|
||||
<v-col :cols="10">
|
||||
<v-col :cols="sliderCols || 8">
|
||||
<v-slider
|
||||
:value="localValue"
|
||||
dark
|
||||
@@ -12,7 +15,8 @@
|
||||
:max="max"
|
||||
:min="min"
|
||||
hide-details
|
||||
color="#ffd843"
|
||||
color="accent"
|
||||
:disabled="disabled"
|
||||
:step="step"
|
||||
@start="isClicked = true"
|
||||
@end="isClicked = false"
|
||||
@@ -25,6 +29,7 @@
|
||||
dark
|
||||
:max="max"
|
||||
:min="min"
|
||||
:disabled="disabled"
|
||||
:value="localValue"
|
||||
class="mt-0 pt-0"
|
||||
hide-details
|
||||
@@ -47,7 +52,7 @@
|
||||
export default {
|
||||
name: "Slider",
|
||||
// eslint-disable-next-line vue/require-prop-types
|
||||
props: ["min", "max", "name", "value", "step"],
|
||||
props: ["min", "max", "name", "value", "step", "sliderCols", "disabled"],
|
||||
data() {
|
||||
return {
|
||||
isFocused: false,
|
||||
@@ -63,7 +68,7 @@ export default {
|
||||
set(value) {
|
||||
this.$emit("input", value);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleChange(val) {
|
||||
|
||||
@@ -1,59 +1,25 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row
|
||||
style="width: 400px;"
|
||||
align="center"
|
||||
>
|
||||
<canvas
|
||||
id="canvasId"
|
||||
width="800"
|
||||
height="800"
|
||||
/>
|
||||
</v-row>
|
||||
<v-row
|
||||
style="width: 400px;"
|
||||
align="center"
|
||||
>
|
||||
<v-simple-table
|
||||
style="text-align: center;background-color: transparent; display: block;margin: auto"
|
||||
dense
|
||||
dark
|
||||
<v-row>
|
||||
<v-col
|
||||
align="center"
|
||||
cols="12"
|
||||
>
|
||||
<template v-slot:default>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-center">
|
||||
Target
|
||||
</th>
|
||||
<th class="text-center">
|
||||
X
|
||||
</th>
|
||||
<th class="text-center">
|
||||
Y
|
||||
</th>
|
||||
<th class="text-center">
|
||||
Angle
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr
|
||||
v-for="(target, index) in targets"
|
||||
:key="index"
|
||||
>
|
||||
<td>{{ index }}</td>
|
||||
<td>{{ target.pose.translation.x.toFixed(2) }}</td>
|
||||
<td>{{ target.pose.translation.y.toFixed(2) }}</td>
|
||||
<td>{{ target.pose.rotation.radians.toFixed(2) }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</template>
|
||||
</v-simple-table>
|
||||
<span class="text--white">Target Location</span>
|
||||
<canvas
|
||||
id="canvasId"
|
||||
class="mt-2"
|
||||
width="800"
|
||||
height="800"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import theme from "../../../theme";
|
||||
|
||||
export default {
|
||||
name: "MiniMap",
|
||||
props: {
|
||||
@@ -136,7 +102,7 @@
|
||||
// so the rect needs to be offset accordingly when drawn
|
||||
this.ctx.rect(-this.targetWidth / 2, -this.targetHeight / 2, this.targetWidth, this.targetHeight);
|
||||
|
||||
this.ctx.fillStyle = "#01a209";
|
||||
this.ctx.fillStyle = theme.accent;
|
||||
this.ctx.fill();
|
||||
|
||||
// restore the context to its untranslated/unrotated state
|
||||
@@ -176,7 +142,7 @@
|
||||
#canvasId {
|
||||
width: 400px;
|
||||
height: 400px;
|
||||
background-color: #2b2b2b;
|
||||
background-color: #232C37;
|
||||
border-radius: 5px;
|
||||
border: 2px solid grey;
|
||||
box-shadow: 0 0 5px 1px;
|
||||
|
||||
@@ -2,27 +2,31 @@
|
||||
<div>
|
||||
<v-row align="center">
|
||||
<v-col
|
||||
:cols="3"
|
||||
class=""
|
||||
cols="10"
|
||||
md="5"
|
||||
lg="10"
|
||||
class="pt-0 pb-0 pl-6"
|
||||
>
|
||||
<div style="padding-left:30px">
|
||||
<CVselect
|
||||
v-if="isCameraNameEdit === false"
|
||||
v-model="currentCameraIndex"
|
||||
name="Camera"
|
||||
:list="$store.getters.cameraList"
|
||||
@input="handleInput('currentCamera',currentCameraIndex)"
|
||||
/>
|
||||
<CVinput
|
||||
v-else
|
||||
v-model="newCameraName"
|
||||
name="Camera"
|
||||
:error-message="checkCameraName"
|
||||
@Enter="saveCameraNameChange"
|
||||
/>
|
||||
</div>
|
||||
<CVselect
|
||||
v-if="isCameraNameEdit === false"
|
||||
v-model="currentCameraIndex"
|
||||
name="Camera"
|
||||
:list="$store.getters.cameraList"
|
||||
@input="handleInput('currentCamera',currentCameraIndex)"
|
||||
/>
|
||||
<CVinput
|
||||
v-else
|
||||
v-model="newCameraName"
|
||||
name="Camera"
|
||||
:error-message="checkCameraName"
|
||||
@Enter="saveCameraNameChange"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col :cols="1">
|
||||
<v-col
|
||||
cols="2"
|
||||
md="1"
|
||||
lg="2"
|
||||
>
|
||||
<CVicon
|
||||
v-if="isCameraNameEdit === false"
|
||||
color="#c5c5c5"
|
||||
@@ -51,8 +55,10 @@
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col
|
||||
:cols="3"
|
||||
class=""
|
||||
cols="10"
|
||||
md="5"
|
||||
lg="10"
|
||||
class="pt-0 pb-0 pl-6"
|
||||
>
|
||||
<CVselect
|
||||
v-model="currentPipelineIndex"
|
||||
@@ -62,14 +68,12 @@
|
||||
/>
|
||||
</v-col>
|
||||
<v-col
|
||||
v-if="currentPipelineIndex !== 0"
|
||||
:cols="1"
|
||||
class=""
|
||||
md="3"
|
||||
cols="2"
|
||||
md="1"
|
||||
lg="2"
|
||||
>
|
||||
<v-menu
|
||||
offset-y
|
||||
dark
|
||||
auto
|
||||
>
|
||||
<template v-slot:activator="{ on }">
|
||||
@@ -125,14 +129,14 @@
|
||||
</v-menu>
|
||||
</v-col>
|
||||
|
||||
<v-btn
|
||||
outlined
|
||||
color="#ffd843"
|
||||
@click="handleInput('command','save')"
|
||||
>
|
||||
<v-icon>save</v-icon>
|
||||
Save
|
||||
</v-btn>
|
||||
<!-- <v-btn-->
|
||||
<!-- outlined-->
|
||||
<!-- color="accent"-->
|
||||
<!-- @click="handleInput('command','save')"-->
|
||||
<!-- >-->
|
||||
<!-- <v-icon>save</v-icon>-->
|
||||
<!-- Save-->
|
||||
<!-- </v-btn>-->
|
||||
</v-row>
|
||||
<!--pipeline duplicate dialog-->
|
||||
<v-dialog
|
||||
@@ -265,15 +269,15 @@
|
||||
for (let cam in this.cameraList) {
|
||||
if (this.cameraList.hasOwnProperty(cam)) {
|
||||
if (this.newCameraName === this.cameraList[cam]) {
|
||||
return "Camera by that name already exists"
|
||||
return "A camera by that name already Exists"
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return "Camera name can only contain letters, numbers and spaces"
|
||||
return "A camera name can only contain letters, numbers and spaces"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
return "";
|
||||
},
|
||||
checkPipelineName() {
|
||||
if (this.newPipelineName !== this.$store.getters.pipelineList[this.currentPipelineIndex - 1] || this.isPipelineNameEdit === false) {
|
||||
@@ -286,7 +290,7 @@
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return "Pipeline name can only contain letters, numbers, and spaces"
|
||||
return "A pipeline name can only contain letters, numbers, and spaces"
|
||||
}
|
||||
}
|
||||
return ""
|
||||
|
||||
Reference in New Issue
Block a user