Added sensors component

This commit is contained in:
Fabio Manganiello 2021-03-27 17:49:37 +01:00
parent 88b788430d
commit 6ec31a253f
15 changed files with 179 additions and 131 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,10 +1,10 @@
<template>
<div class="run component-row" @click="run">
<div :class="{'col-10': hasIcon, 'col-12': !hasIcon}" v-text="name" />
<div class="col-2 icon-container" v-if="hasIcon">
<div class="col-1 icon-container" v-if="hasIcon">
<img class="icon" :src="iconUrl" :alt="name" v-if="iconUrl?.length">
<i class="icon" :class="iconClass" :style="iconStyle" v-else />
</div>
<div :class="{'col-11': hasIcon, 'col-12': !hasIcon}" v-text="name" />
</div>
</template>
@ -17,63 +17,9 @@ import mixins from './mixins';
export default {
name: "Run",
mixins: [mixins],
props: {
/**
* Component name
*/
name: {
type: String,
default: '[Unnamed action]',
},
/**
* Action (FontAwesome) icon class (default: `fa fa-play`)
*/
iconClass: {
type: String,
},
/**
* Action icon URL (default: `fa fa-play`)
*/
iconUrl: {
type: String,
},
/**
* Action icon color override, for FontAwesome icons
*/
iconColor: {
type: String,
},
},
computed: {
iconStyle() {
if (!this.iconClass?.length && this.iconColor?.length)
return
return {'color': this.iconColor}
},
hasIcon() {
return this.iconUrl?.length || this.iconClass?.length
},
}
}
</script>
<style lang="scss" scoped>
@import "mixins";
.run {
.icon-container {
position: relative;
.icon {
position: absolute;
right: 0;
}
}
}
</style>

View File

@ -0,0 +1,68 @@
<template>
<div class="sensor component-row" @click="run">
<div class="col-1 icon-container" v-if="hasIcon">
<img class="icon" :src="iconUrl" :alt="name" v-if="iconUrl?.length">
<i class="icon" :class="iconClass" :style="iconStyle" v-else />
</div>
<div :class="{'col-8': hasIcon, 'col-9': !hasIcon}" v-text="name" />
<div class="col-3 value-container">
<div class="value">
{{ value }}
<span v-if="unit" v-text="unit" />
</div>
</div>
</div>
</template>
<script>
import mixins from './mixins';
/**
* This component is used to monitor values from sensors.
*/
export default {
name: "Sensor",
mixins: [mixins],
props: {
/**
* Optional unit used for the sensor value
*/
unit: {
type: String,
},
},
methods: {
async run() {
if (this.handlers.beforeActions)
await this.handlers.beforeActions(this)
if (this.actions?.length)
for (const action of this.actions)
await this.request_(action)
else
await this.refresh()
if (this.handlers.afterActions) {
await this.handlers.afterActions(this)
}
},
}
}
</script>
<style lang="scss" scoped>
@import "mixins";
.sensor {
.value-container {
position: relative;
.value {
position: absolute;
right: 0;
font-weight: bold;
}
}
}
</style>

View File

@ -1,6 +1,10 @@
<template>
<div class="slider-root component-row">
<div class="col-7" v-text="name" />
<div class="col-1 icon-container" v-if="hasIcon">
<img class="icon" :src="iconUrl" :alt="name" v-if="iconUrl?.length">
<i class="icon" :class="iconClass" :style="iconStyle" v-else />
</div>
<div :class="{'col-6': hasIcon, 'col-7': !hasIcon}" v-text="name" />
<div class="col-5 slider-container">
<div class="slider">
<SliderElement :value="value" :range="[parseFloat(min), parseFloat(max)]" @mouseup="run" />
@ -22,14 +26,6 @@ export default {
components: {SliderElement},
mixins: [mixins],
props: {
/**
* Display name for this slider.
*/
name: {
type: String,
default: '[Unnamed slider]',
},
/**
* Minimum value for the slider (default: 0).
*/
@ -60,12 +56,6 @@ export default {
}
},
},
data() {
return {
value: undefined,
}
},
}
</script>

View File

@ -1,6 +1,10 @@
<template>
<div class="switch component-row" @click="run">
<div class="col-10" v-text="name" />
<div class="col-1 icon-container" v-if="hasIcon">
<img class="icon" :src="iconUrl" :alt="name" v-if="iconUrl?.length">
<i class="icon" :class="iconClass" :style="iconStyle" v-else />
</div>
<div :class="{'col-9': hasIcon, 'col-10': !hasIcon}" v-text="name" />
<div class="col-2 toggle-container">
<div class="toggle">
<ToggleSwitch :value="value" @input.stop="run" />
@ -21,21 +25,6 @@ export default {
name: "Switch",
components: {ToggleSwitch},
mixins: [mixins],
props: {
/**
* Display name for this switch.
*/
name: {
type: String,
default: '[Unnamed switch]',
},
},
data() {
return {
value: undefined,
}
},
}
</script>

View File

@ -3,51 +3,88 @@ import Utils from "@/Utils";
export default {
mixins: [Utils],
props: {
// Actions to run upon interaction with the widget. Format:
//
// [
// {
// "action": "light.hue.toggle",
// "args": {
// "lights": ["Bulb 1", "Bulb 2"]
// }
// },
// {
// "action": "music.mpd.pause"
// }
// ]
/**
* Component name
*/
name: {
type: String,
default: '[Unnamed sensor]',
},
/**
* Action (FontAwesome) icon class (default: `fa fa-play`)
*/
iconClass: {
type: String,
},
/**
* Action icon URL (default: `fa fa-play`)
*/
iconUrl: {
type: String,
},
/**
* Action icon color override, for FontAwesome icons
*/
iconColor: {
type: String,
},
/**
* Actions to run upon interaction with the widget. Format:
*
* [
* {
* "action": "light.hue.toggle",
* "args": {
* "lights": ["Bulb 1", "Bulb 2"]
* }
* },
* {
* "action": "music.mpd.pause"
* }
* ]
*/
actions: {
type: Array,
default: () => { return [] },
},
// Map of variables used by this component, in the form
// of variable_name -> variable_value.
/**
* Map of variables used by this component, in the form
* variable_name -> variable_value.
*/
_vars: {
type: Object,
default: () => { return {} },
},
// Map of handlers, in the form of event_type -> functions.
// Supported event handler types:
//
// - mounted: Function to execute when the component is mounted.
// - beforeActions: Function to execute before the component action is run.
// - afterActions: Function to execute after the component action is run.
// - refresh: Function to be called at startup (if mounted is also specified
// then refresh will be called after mounted when the component is
// first mounted) and at regular intervals defined on the
// interval property (default: 10 seconds).
// - events: This is a mapping of functions that react to Platypush
// platform events published on the websocket (e.g. lights or
// switches toggles, media events etc.). The form is
// platypush_event_type -> function.
/**
* Map of handlers, in the form of event_type -> functions.
* Supported event handler types:
*
* - mounted: Function to execute when the component is mounted.
* - beforeActions: Function to execute before the component action is run.
* - afterActions: Function to execute after the component action is run.
* - refresh: Function to be called at startup (if mounted is also specified
* then refresh will be called after mounted when the component is
* first mounted) and at regular intervals defined on the
* interval property (default: 10 seconds).
* - events: This is a mapping of functions that react to Platypush
* platform events published on the websocket (e.g. lights or
* switches toggles, media events etc.). The form is
* platypush_event_type -> function.
*/
handlers: {
type: Object,
default: () => { return {} },
},
// Event bus
/**
* Event bus
*/
bus: {
type: Object,
},
@ -60,9 +97,23 @@ export default {
refresh: null,
refreshInterval: null,
value: null,
loading: false,
}
},
computed: {
iconStyle() {
if (!this.iconClass?.length && this.iconColor?.length)
return
return {'color': this.iconColor}
},
hasIcon() {
return this.iconUrl?.length || this.iconClass?.length
},
},
methods: {
async run() {
if (this.handlers.input)

View File

@ -1,9 +1,11 @@
import Run from './components/Run'
import Switch from './components/Switch'
import Slider from './components/Slider'
import Sensor from "@/components/widgets/Component/components/Sensor";
export default {
Run,
Switch,
Slider,
Sensor,
}