Colour propery box on input, flash green on update, only modal notify if value is not set exactly
This commit is contained in:
parent
80ee303ac9
commit
212b8fe062
3 changed files with 90 additions and 9 deletions
|
|
@ -6,6 +6,7 @@
|
|||
<input
|
||||
v-model="internalValue"
|
||||
class="uk-form-small numeric-setting-line-input"
|
||||
:class="{ edited: isEdited, flash: animateUpdate }"
|
||||
type="number"
|
||||
@focusin="focusIn"
|
||||
@focusout="focusOut"
|
||||
|
|
@ -35,7 +36,9 @@
|
|||
:key="i"
|
||||
v-model="internalValue[i - 1]"
|
||||
class="uk-form-small numeric-setting-line-input"
|
||||
:class="{ edited: isEdited, flash: animateUpdate }"
|
||||
type="number"
|
||||
@input="updateIsEdited"
|
||||
@focusin="focusIn"
|
||||
@focusout="focusOut"
|
||||
@keydown="keyDown"
|
||||
|
|
@ -51,7 +54,9 @@
|
|||
<input
|
||||
v-model="internalValue[key]"
|
||||
class="uk-form-small numeric-setting-line-input"
|
||||
:class="{ edited: isEdited, flash: animateUpdate }"
|
||||
type="number"
|
||||
@input="updateIsEdited"
|
||||
@focusin="focusIn"
|
||||
@focusout="focusOut"
|
||||
@keydown="keyDown"
|
||||
|
|
@ -95,19 +100,50 @@ export default {
|
|||
type: String,
|
||||
default: ""
|
||||
},
|
||||
animate: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
internalValue: this.value,
|
||||
valueOnEnter: undefined,
|
||||
focused: false
|
||||
// Initialise with a copy. As this is faster than stringifying and parsing.
|
||||
internalValue: Array.isArray(this.value)
|
||||
? [...this.value]
|
||||
: typeof this.value === 'object'
|
||||
? { ...this.value }
|
||||
: this.value,
|
||||
// Is edited can't be computed as we mutate internalValue
|
||||
isEdited: false,
|
||||
animateUpdate: false,
|
||||
};
|
||||
},
|
||||
|
||||
mounted() {
|
||||
if (this.value !== undefined) {
|
||||
this.resetInternalValue();
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
value(newValue) {
|
||||
this.internalValue = newValue;
|
||||
value() {
|
||||
// Fire updateIsEdited on both value and internal value change,
|
||||
// as change in value may not causse internalValue to change.
|
||||
this.updateIsEdited();
|
||||
this.resetInternalValue();
|
||||
},
|
||||
internalValue() {
|
||||
this.updateIsEdited();
|
||||
},
|
||||
animate(updated) {
|
||||
if (updated) {
|
||||
this.animateUpdate = true;
|
||||
setTimeout(() => {
|
||||
this.animateUpdate = false;
|
||||
this.$emit('animationShown');
|
||||
}, 700);
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -170,6 +206,10 @@ export default {
|
|||
},
|
||||
|
||||
methods: {
|
||||
resetInternalValue: function() {
|
||||
// stringify and parse to ensure no internal mutation for objects
|
||||
this.internalValue = JSON.parse(JSON.stringify(this.value));
|
||||
},
|
||||
requestUpdate: async function() {
|
||||
this.$emit("requestUpdate")
|
||||
},
|
||||
|
|
@ -195,7 +235,23 @@ export default {
|
|||
if (event.keyCode == 13) {
|
||||
this.sendValue();
|
||||
}
|
||||
},
|
||||
updateIsEdited: function() {
|
||||
this.isEdited = this.deepStringify(this.internalValue) !== this.deepStringify(this.value);
|
||||
},
|
||||
deepStringify: function(val) {
|
||||
if (Array.isArray(val)) {
|
||||
return JSON.stringify(val.map(String));
|
||||
}
|
||||
if (val && typeof val === 'object') {
|
||||
const normalized = Object.fromEntries(
|
||||
Object.entries(val).map(([k, v]) => [k, String(v)])
|
||||
);
|
||||
return JSON.stringify(normalized);
|
||||
}
|
||||
return JSON.stringify(String(val));
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -215,4 +271,14 @@ export default {
|
|||
margin-right: 5px;
|
||||
width: 6em;
|
||||
}
|
||||
.edited {
|
||||
background-color: #fff3cd;
|
||||
}
|
||||
@keyframes green-flash {
|
||||
0% { background-color: #3fda63; }
|
||||
100% { background-color: white; }
|
||||
}
|
||||
.flash {
|
||||
animation: green-flash 0.7s ease;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@
|
|||
v-model="value"
|
||||
:data-schema="propertyDescription"
|
||||
:label="label"
|
||||
:animate="animate"
|
||||
@requestUpdate="readProperty"
|
||||
@sendValue="writeProperty"
|
||||
@animationShown="resetAnimate"
|
||||
/>
|
||||
</template>
|
||||
|
||||
|
|
@ -45,7 +47,8 @@ export default {
|
|||
|
||||
data() {
|
||||
return {
|
||||
value: undefined
|
||||
value: undefined,
|
||||
animate: false
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -98,14 +101,15 @@ export default {
|
|||
await new Promise(r => setTimeout(r, this.readBackDelay));
|
||||
let newVal = await this.readProperty();
|
||||
if (newVal == requestedValue) {
|
||||
await this.modalNotify(`Set ${this.label} to ${newVal}.`);
|
||||
this.animate = true;
|
||||
} else {
|
||||
this.animate = true;
|
||||
await this.modalNotify(
|
||||
`Set ${this.label} to ${newVal} (requested ${requestedValue}).`
|
||||
`Set ${this.label} to ${newVal} (closest valid value to requested ${requestedValue}).`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
await this.modalNotify(`Set ${this.label} to ${this.value}.`);
|
||||
this.animate = true;
|
||||
}
|
||||
} catch (error) {
|
||||
// Use mixin to display error
|
||||
|
|
@ -113,6 +117,9 @@ export default {
|
|||
// Re-read property to try to update to server value
|
||||
this.readProperty();
|
||||
}
|
||||
},
|
||||
resetAnimate: function() {
|
||||
this.animate = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,8 +10,10 @@
|
|||
v-model="backgroundDetectorStatus.settings"
|
||||
:data-schema="backgroundDetectorStatus.settings_schema"
|
||||
label=""
|
||||
:animate="animate"
|
||||
@requestUpdate="readSettings"
|
||||
@sendValue="writeSettings"
|
||||
@animationShown="resetAnimate"
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
|
|
@ -57,6 +59,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
backgroundDetectorStatus: undefined,
|
||||
animate: false
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -87,6 +90,11 @@ export default {
|
|||
"update_detector_settings",
|
||||
{"data": requestedValue}
|
||||
);
|
||||
this.animate = true;
|
||||
this.readSettings();
|
||||
},
|
||||
resetAnimate: function() {
|
||||
this.animate = false;
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue