From 488493385f313c15cf95f6b2a3e4bbed323e2ab0 Mon Sep 17 00:00:00 2001 From: Richard Bowman Date: Wed, 29 Nov 2023 23:54:00 +0000 Subject: [PATCH] Combine the various property controls into one component propertyControl now handles several different property types, based on the thing description. This reduces duplication and should keep the code cleaner. In the future this will become a part of a labthings-vue package, I hope! --- .../labThingsComponents/propertyControl.vue | 77 ++++++++++++++++--- .../aboutComponents/statusPane.vue | 17 ++-- .../settingsComponents/cameraSettings.vue | 38 +++++---- 3 files changed, 100 insertions(+), 32 deletions(-) diff --git a/webapp/src/components/labThingsComponents/propertyControl.vue b/webapp/src/components/labThingsComponents/propertyControl.vue index b4ec48a6..940ce95f 100644 --- a/webapp/src/components/labThingsComponents/propertyControl.vue +++ b/webapp/src/components/labThingsComponents/propertyControl.vue @@ -44,7 +44,7 @@ refresh -
+
{ return { - value: {}, + value: undefined, valueOnEnter: undefined, focused: false }; @@ -90,21 +94,35 @@ export default { return this.readBackDelay !== undefined; }, propertyDescription: function() { - return this.thingDescription.properties[this.propertyName]; + try { + return this.thingDescription.properties[this.propertyName]; + } catch (error) { + return undefined; + } + }, + readPropertyUrl: function() { + let href = this.formHref("readproperty"); + return this.prependTdBaseUri(href); + }, + writePropertyUrl: function() { + let href = this.formHref("writeproperty"); + return this.prependTdBaseUri(href); }, dataType: function() { let prop = this.propertyDescription; + if (prop == undefined) { + return "undefined"; + } const num_types = ["integer", "float", "number"]; if (num_types.includes(prop.type)) { return "number"; } - console.log("Prop type", prop.type, "is not in", num_types); if (prop.type == "array") { - if (num_types.includes(prop.items)) { + if (num_types.includes(prop.items.type)) { return "number_array"; } if (Array.isArray(prop.items)) { - if (prop.items.every(t => num_types.includes(t))) { + if (prop.items.every(t => num_types.includes(t.type))) { return "number_array"; } } @@ -125,21 +143,60 @@ export default { } }, + watch: { + readPropertyUrl: function() { + // Ensure we read the property once the URL is known + this.readProperty(); + } + }, + mounted: function() { - this.readProperty(); + // Read the property when we're mounted - usually this won't + // work because the URL isn't set yet. However, it's helpful if + // the app is reloaded (e.g. from a dev server). + if (this.value == undefined) { + this.readProperty(); + } }, methods: { + formHref: function(op = "readproperty") { + if (this.thingDescription == undefined) return undefined; + try { + let forms = this.propertyDescription.forms; + let readForm = forms.find(f => f.op == op || f.op.includes(op)); + return readForm.href; + } catch (error) { + console.log( + `Failed to find form for ${op} on ${this.propertyName}`, + error + ); + return undefined; + } + }, + prependTdBaseUri: function(href) { + if (href == undefined) return undefined; + if (href.startsWith("http")) return href; + if ("base" in this.thingDescription) { + if (href.startsWith("/")) href = href.slice(1); + if (!this.thingDescription.base.endsWith("/")) + this.thingDescription.base += "/"; + return this.thingDescription.base + href; + } + return href; + }, readProperty: async function() { - let response = await axios.get(this.propertyUrl); + console.log(`Reading property ${this.propertyName}`); + let response = await axios.get(this.readPropertyUrl); + console.log(`Read property ${this.propertyName}`); this.value = response.data; - console.log("Read property", this.propertyUrl, response.data); + console.log("Read property", this.readPropertyUrl, response.data); return response.data; }, writeProperty: async function() { try { let requestedValue = this.value; - await axios.post(this.propertyUrl, requestedValue); + await axios.post(this.writePropertyUrl, requestedValue); if (this.readBack) { await new Promise(r => setTimeout(r, this.readBackDelay)); let newVal = await this.readProperty(); diff --git a/webapp/src/components/tabContentComponents/aboutComponents/statusPane.vue b/webapp/src/components/tabContentComponents/aboutComponents/statusPane.vue index 1ec9103b..e23999b6 100644 --- a/webapp/src/components/tabContentComponents/aboutComponents/statusPane.vue +++ b/webapp/src/components/tabContentComponents/aboutComponents/statusPane.vue @@ -87,7 +87,7 @@ export default { computed: { baseUri: function() { return `${this.$store.getters.baseUri}/`; - }, + } }, mounted: function() { @@ -98,7 +98,7 @@ export default { methods: { updateConfiguration: async function() { - console.log("Showing the configuration is not yet fully implemented") + console.log("Showing the configuration is not yet fully implemented"); // Retrieve TDs for camera and stage let things = {}; for (let thing of ["camera", "stage"]) { @@ -106,17 +106,20 @@ export default { let response = await axios.get(this.baseUri + thing); // Get Thing Description things[thing] = response.data; } catch (error) { - console.log(thing + " was missing", error) + console.log(thing + " was missing", error); } } - this.things = things; // We must set this.things in order to trigger the UI update + this.things = things; // We must set this.things in order to trigger the UI update }, updateActions: async function() { try { let response = await axios.get(this.baseUri + "system_control"); // Get Thing Description this.systemControlActions = response.data.actions; } catch (error) { - console.log("system control was missing - shutdown/restart buttons will not appear", error) + console.log( + "system control was missing - shutdown/restart buttons will not appear", + error + ); } }, shutdownRequest: function() { @@ -124,7 +127,7 @@ export default { () => { this.$store.commit("resetState"); // Post and silence errors - axios.post(this.baseUri + 'system_control/shutdown').catch(() => {}); + axios.post(this.baseUri + "system_control/shutdown").catch(() => {}); }, () => {} ); @@ -134,7 +137,7 @@ export default { () => { this.$store.commit("resetState"); // Post and silence errors - axios.post(this.baseUri + 'system_control/restart').catch(() => {}); + axios.post(this.baseUri + "system_control/restart").catch(() => {}); }, () => {} ); diff --git a/webapp/src/components/tabContentComponents/settingsComponents/cameraSettings.vue b/webapp/src/components/tabContentComponents/settingsComponents/cameraSettings.vue index 9c768c46..f9e70ebb 100644 --- a/webapp/src/components/tabContentComponents/settingsComponents/cameraSettings.vue +++ b/webapp/src/components/tabContentComponents/settingsComponents/cameraSettings.vue @@ -12,19 +12,22 @@
  • Pi Camera Settings
    - - -
    @@ -32,14 +35,16 @@
  • Image Quality
    - -
    @@ -92,8 +97,7 @@