UI bug fixes and feature refinements (#59)

* Rework settings page; touch up contour, output, and 3D tabs; font sizing

No stream placeholder; driver mode refined; cameras page

Make settings snackbar work

Lint fix

Fix settings page padding

Actually hide settings fields if unsupported

* Make toggle buttons less confusing; fix driver toggle; form validation

* Make eyedropper work and make input/select styling more consistent

* Fix color picker and tabbing bugs

* Set up camera and settings pages to talk to the backend

* Add auto reconnect

* Add lots of tooltips and improve related thematic consistency

* Only show output stream while color picking

* Unbreak robot offset

* Increase tooltip delay and refactor tooltip label into a component

* Remove toggle button switching behavior

* Fix PnP tab and add a flag to disable FOV configuration

* Move FPS indicator

* Make GPU acceleration status use one value in the store

* Only allow IPv4 static IPs and remove accidentally committed index
This commit is contained in:
Declan Freeman-Gleason
2020-07-31 13:50:50 -07:00
committed by GitHub
parent 0b98dc3c9f
commit 19b57235fe
34 changed files with 1099 additions and 566 deletions

View File

@@ -1,86 +1,55 @@
<template>
<div>
<div style="margin-top: 15px">
<span>General Settings:</span>
<v-divider color="white" />
</div>
<CVnumberinput
v-model="settings.teamNumber"
name="Team Number"
/>
<CVradio
v-model="settings.connectionType"
:list="['DHCP','Static']"
/>
<v-divider color="white" />
<CVinput
v-model="settings.ip"
name="IP"
:disabled="isDisabled"
/>
<CVinput
v-model="settings.netmask"
name="NetMask"
:disabled="isDisabled"
/>
<CVinput
v-model="settings.gateway"
name="Gateway"
:disabled="isDisabled"
/>
<v-divider color="white" />
<CVinput
v-model="settings.hostname"
name="Hostname"
/>
<v-btn
style="margin-top:10px"
small
color="#ffd843"
@click="sendGeneralSettings"
>
Save General Settings
</v-btn>
<div style="margin-top: 20px">
<span>Install or Update:</span>
<v-divider color="white" />
</div>
<div v-if="!isLoading">
<v-row
dense
align="center"
<span>Version: {{ settings.version }}</span>
&mdash;
<span>Hardware model: {{ settings.hardwareModel }}</span>
&mdash;
<span>Platform: {{ settings.hardwarePlatform }}</span>
&mdash;
<span>GPU Acceleration: {{ settings.gpuAcceleration ? "Enabled" : "Unsupported" }}{{ settings.gpuAcceleration ? " (" + settings.gpuAcceleration + " mode)" : "" }}</span>
<v-row>
<v-col
cols="12"
sm="6"
lg="4"
>
<v-col :cols="3">
<span>Choose a newer version: </span>
</v-col>
<v-col :cols="6">
<v-file-input
v-model="file"
accept=".jar"
dark
/>
</v-col>
</v-row>
<v-btn
small
@click="installOrUpdate"
<v-btn
color="secondary"
@click="$refs.exportSettings.click()"
>
<v-icon left>
mdi-download
</v-icon> Export Settings
</v-btn>
</v-col>
<v-col
cols="12"
sm="6"
lg="4"
>
{{ fileUploadText }}
</v-btn>
</div>
<div
v-else
style="text-align: center; margin-top: 20px"
>
<v-progress-circular
color="white"
:indeterminate="true"
size="32"
width="4"
/>
<br>
<span>Please wait this may take a while</span>
</div>
<v-btn
color="secondary"
@click="$refs.importSettings.click()"
>
<v-icon left>
mdi-upload
</v-icon> Import Settings
</v-btn>
</v-col>
<v-col
cols="12"
lg="4"
>
<v-btn
color="red"
@click="restartDevice"
>
<v-icon left>
mdi-restart
</v-icon> Restart Device
</v-btn>
</v-col>
</v-row>
<v-snackbar
v-model="snack"
top
@@ -88,101 +57,70 @@
>
<span>{{ snackbar.text }}</span>
</v-snackbar>
<!-- Special hidden upload input that gets 'clicked' when the user imports settings -->
<input
ref="importSettings"
type="file"
accept=".zip"
style="display: none;"
@change="readImportedSettings"
>
<!-- Special hidden link that gets 'clicked' when the user exports settings -->
<a
ref="exportSettings"
style="color: black; text-decoration: none; display: none"
href="/api/settings/export"
download="photonvision-settings.zip"
/>
</div>
</template>
<script>
import CVnumberinput from '../../components/common/cv-number-input'
import CVradio from '../../components/common/cv-radio'
import CVinput from '../../components/common/cv-input'
export default {
name: 'General',
components: {
CVnumberinput,
CVradio,
CVinput
},
data() {
return {
file: undefined,
snackbar: {
color: "success",
text: ""
},
snack: false,
isLoading: false
}
return {
snack: false,
snackbar: {
color: "success",
text: ""
},
}
},
computed: {
fileUploadText() {
if (this.file !== undefined) {
return "Update and run at startup"
} else {
return "Run current version at startup"
}
},
isDisabled() {
return this.settings.connectionType === 0;
},
settings: {
get() {
return this.$store.state.settings;
}
}
settings() {
return this.$store.state.settings.general;
}
},
methods: {
sendGeneralSettings() {
const self = this;
this.axios.post("http://" + this.$address + "/api/settings/general", this.settings).then(
function (response) {
if (response.status === 200) {
self.snackbar = {
color: "success",
text: "Save successful, Please restart for changes to take action"
};
self.snack = true;
}
},
function (error) {
self.snackbar = {
color: "error",
text: error.response.data
};
self.snack = true;
}
)
},
installOrUpdate() {
let formData = new FormData();
formData.append('file', this.file);
if (this.file !== undefined) {
this.isLoading = true;
}
this.axios.post("http://" + this.$address + "/api/install", formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(() => {
this.snackbar = {
color: "success",
text: "Installation successful"
};
this.isLoading = false;
this.snack = true;
}).catch(error => {
this.snackbar = {
color: "error",
text: error.response.data
};
this.isLoading = false;
this.snack = true;
})
}
readImportedSettings(event) {
let formData = new FormData();
formData.append("zipData", event.target.files[0]);
this.axios.post("http://" + this.$address + "/api/settings/import", formData,
{headers: {"Content-Type": "multipart/form-data"}}).then(() => {
this.snackbar = {
color: "success",
text: "Settings imported successfully",
};
}).catch(() => {
this.snackbar = {
color: "error",
text: "Couldn't import settings",
}
});
this.snack = true;
},
restartDevice() {
this.axios.post("http://" + this.$address + "/api/restart");
}
}
}
</script>
<style lang="" scoped>
<style lang="css" scoped>
.v-btn {
width: 100%;
}
</style>