123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- <template>
- <div class="nrdb-ui-led" :style="`--ui-led-shadow-width: ${size * 0.1}px; --ui-led-border-width: ${size * 0.15}px; --ui-led-color: ${color}; flex-direction: ${flexDirection}`">
- <label v-if="props.label" class="nrdb-ui-led-label v-label" :style="`justify-content: ${labelAlignment}`">{{ props.label }}</label>
- <span ref="led" class="nrdb-ui-led-bulb" :class="`${hasValue ? 'nrdb-ui-led-bulb-on' : ''} nrdb-ui-led-bulb--${props.shape} ${props.showGlow && hasValue ? 'nrdb-ui-led-bulb--glow' : ''} ${props.showBorder ? 'nrdb-ui-led-bulb--border' : ''}`">{{ value !== null ? value : 'No Message Received' }}</span>
- </div>
- </template>
-
- <script>
- import { mapState } from 'vuex'
-
- export default {
- name: 'UILed',
- inject: ['$socket'],
- props: {
- id: { type: String, required: true },
- props: { type: Object, default: () => ({}) },
- state: { type: Object, default: () => ({ enabled: false, visible: false }) }
- },
- data () {
- return {
- size: 24
- }
- },
- computed: {
- ...mapState('data', ['messages']),
- hasValue: function () {
- return this.messages[this.id] !== undefined
- },
- flexDirection: function () {
- return this.props.labelPlacement === 'left' ? 'row' : 'row-reverse'
- },
- labelAlignment: function () {
- return this.props.labelAlignment
- },
- color: function () {
- if (this.hasValue && this.props.evaluated) {
- const msg = this.messages[this.id]
- // check which, if any, color we should be displaying
- for (const i in this.props.evaluated) {
- const state = this.props.evaluated[i]
- if (typeof (state.value) === 'object') {
- if (JSON.stringify(state.value) === JSON.stringify(msg.payload)) {
- return state.color
- }
- } else if (state.value === msg.payload) {
- return state.color
- }
- }
- }
- return 'gray'
- }
- },
- mounted () {
- this.$socket.on('widget-load:' + this.id, (msg) => {
- // load the latest message from the Node-RED datastore when this widget is loaded
- // storing it in our vuex store so that we have it saved as we navigate around
- this.$store.commit('data/bind', {
- widgetId: this.id,
- msg
- })
- })
- this.$socket.on('msg-input:' + this.id, (msg) => {
- // store the latest message in our client-side vuex store when we receive a new message
- this.$store.commit('data/bind', {
- widgetId: this.id,
- msg
- })
- })
- // tell Node-RED that we're loading a new instance of this widget
- this.$socket.emit('widget-load', this.id)
-
- this.$nextTick(() => {
- this.size = this.$refs.led.clientWidth
- })
- },
- unmounted () {
- /* Make sure, any events you subscribe to on SocketIO are unsubscribed to here */
- this.$socket?.off('widget-load' + this.id)
- this.$socket?.off('msg-input:' + this.id)
- }
- }
- </script>
-
- <style scoped>
- .nrdb-ui-led {
- --ui-led-border-width: 12px;
- --ui-led-shadow-width: 12px;
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 16px;
- }
-
- .nrdb-ui-led-label {
- flex-grow: 1;
- }
-
- .nrdb-ui-led-bulb {
- display: block;
- height: 65%;
- aspect-ratio: 1 / 1;
- background-color: var(--ui-led-color);
- box-shadow: inset #4413138a 0 -1px var(--ui-led-shadow-width) var(--ui-led-shadow-width);
- }
-
- .nrdb-ui-led-bulb-on {
- background: radial-gradient(#ffffff96, #ffffff00 70%), var(--ui-led-color);
- }
-
- .nrdb-ui-led-bulb--square {
- border-radius: 25%;
- }
-
- .nrdb-ui-led-bulb--circle {
- border-radius: 50%;
- }
-
- .nrdb-ui-led-bulb--border {
- border-width: var(--ui-led-border-width);
- border-color: #222;
- border-style: solid;
- }
-
- .nrdb-ui-led-bulb--glow {
- box-shadow: 0 0 calc(1.25 * var(--ui-led-border-width)) var(--ui-led-color), inset #44131340 0 -1px var(--ui-led-shadow-width) var(--ui-led-shadow-width);
- }
- </style>
|