Complete UI for arbitrary dectector settings. Required better method for invoking actions.

Error handling was fixed in the process of getting the above correct.
This commit is contained in:
Julian Stirling 2025-07-28 00:35:24 +01:00
parent 92d15d921b
commit 33413a591a
5 changed files with 102 additions and 25 deletions

View file

@ -51,20 +51,21 @@
</label>
<label v-if="dataType == 'number_object'" class="uk-form-label"
>{{ label }}
<div class="input-and-buttons-container">
<input
v-for="(_v, key) in value"
:key="key"
v-model="internalValue[key]"
class="uk-form-small numeric-setting-line-input"
type="number"
@focusin="focusIn"
@focusout="focusOut"
@keydown="keyDown"
/>
<a class="button-next-to-input" @click="requestUpdate">
<span class="material-symbols-outlined">refresh</span>
</a>
<div v-for="(val, key) in value" :key="key">
<label>{{internalLabels[key]}}</label>
<div class="input-and-buttons-container" >
<input
v-model="internalValue[key]"
class="uk-form-small numeric-setting-line-input"
type="number"
@focusin="focusIn"
@focusout="focusOut"
@keydown="keyDown"
/>
<a class="button-next-to-input" @click="requestUpdate">
<span class="material-symbols-outlined">refresh</span>
</a>
</div>
</div>
</label>
<label v-if="dataType == 'other'" class="uk-form-label"
@ -112,6 +113,16 @@ export default {
}
},
computed: {
internalLabels: function() {
if (this.dataType == "number_object") {
let labels = {};
for (const key in this.internalValue){
labels[key] = this.dataSchema.properties[key].title
}
return labels;
}
return [];
},
valueLength: function() {
if (this.dataType == "number_array") {
if (this.internalValue == undefined) {

View file

@ -10,6 +10,8 @@
v-model="backgroundDetectorStatus.settings"
:data-schema="backgroundDetectorStatus.settings_schema"
label=""
@requestUpdate="readSettings"
@sendValue="writeSettings"
/>
</div>
</li>
@ -72,6 +74,19 @@ export default {
alertImageLabel(r) {
let label = r.output[0] ? "sample" : "background";
this.modalNotify(`Current image is ${label} (${r.output[1]})`);
},
readSettings: async function() {
this.backgroundDetectorStatus = await this.readThingProperty(
"camera",
"background_detector_status"
);
},
writeSettings: async function(requestedValue) {
await this.invokeAction(
"camera",
"update_detector_settings",
{"data": requestedValue}
);
}
},
async created() {

View file

@ -67,6 +67,21 @@ Vue.mixin({
}
await axios.put(url, value);
},
async invokeAction(thing, action, data) {
let url = this.$store.getters["wot/thingActionUrl"](
thing,
action,
"invokeaction",
false
);
try {
let response = await axios.post(url, data);
return response;
} catch (error) {
this.modalError(error);
return undefined;
}
},
thingActionUrl(thing, action, allow_missing = false) {
let url = this.$store.getters["wot/thingActionUrl"](
thing,
@ -132,7 +147,6 @@ Vue.mixin({
modalError: function(error) {
var errormsg = this.getErrorMessage(error);
this.$store.commit("setErrorMessage", errormsg);
console.log("Modal error:", error);
UIkit.notification({
message: `${errormsg}`,
status: "danger"
@ -140,25 +154,43 @@ Vue.mixin({
},
getErrorMessage: function(error) {
// If a response was obtained, format it nicely and return it
// Format the error.
let data = this.getErrorData(error)
// Get error data may get an object. Handle edge cases and if not try to use
// JSON to get the best string. This stops "objectObject" showing as an error.
if (data === null) return "null";
if (data === undefined) return "undefined";
if (typeof data === 'string') return data;
try {
return JSON.stringify(data, null, 2);
} catch (err) {
return String(data);
}
},
getErrorData: function(error){
// If a response was obtained, extract the most specific message
if (error.response) {
// If the response is a nicely formatted JSON response from the server
if (error.response.data.message) {
return `${error.response.data.message}`;
return error.response.data.message;
}
if (error.response.data.detail) {
return `${error.response.data.detail}`;
try {
return error.response.data.detail[0].msg
} catch (err) {
return error.response.data.detail;
}
}
// If the response is just some generic error response
if (error.response.data) {
return `${error.response.data}`;
return error.response.data;
}
return `${error.response}`;
return error.response;
}
// If we have an error object with a message, use that
if (error.message) return `${error.message}`;
// Otherwise attempt to cast it to a string.
return `${error}`;
if (error.message) return error.message;
// At this point just formatting the whole error object is the best we can do.
return error;
},
showModalElement: function(element) {