'use strict'; import "./webui.css"; import { html, render } from 'lit-html'; import { map } from 'lit-html/directives/map.js'; import { ifDefined } from 'lit-html/directives/if-defined.js'; import { unsafeSVG } from 'lit-html/directives/unsafe-svg.js'; import { unsafeHTML } from 'lit-html/directives/unsafe-html.js'; import { connect } from "mqtt"; var client; const connectedSvg = ''; const disconnectedSvg = ''; const backButtonSvg = ''; const goToPage = (pageHash) => { if (typeof pageHash !== 'string') pageHash = location.hash || '#mainpage'; console.log('goToPage', pageHash); document.querySelectorAll(".page").forEach(element => { element.style.display = ('#'+element.id !== pageHash) ? 'none' : ''; }); } const transformMessage = (input, meta) => { if (typeof meta.transform !== 'object') return input; if (typeof meta.transform.set === 'string') { try { return new Function('input', meta.transform.set)(input); } catch (exception){ console.log(exception); return; } } return input; } const onMessage = (topic, message) => { try { message = JSON.parse(message.toString()); } catch(e) { } document.querySelectorAll('[data-mqtt-topic="' + topic + '"]').forEach((element) => { let value = null; if (typeof element.dataset.transform !== 'undefined') { try { value = new Function('topic', 'message', element.dataset.transform)(topic, message); } catch (exception){ console.log(exception); return; } } else { value = message; } if (value === null) value = message; switch (element.dataset.type) { case 'html': element.innerHTML = value; break; case 'text': if (typeof value === 'object') return; element.textContent = value; break; case 'switch': if (typeof value !== 'boolean') return; element.checked = value; break; case 'slider': if (isNaN(value)) return; element.value = value; element.dataset.lastMqttValue = value; element.style.setProperty('--c', 0); break; case 'select': if (typeof value === 'object') return; element.value = value; element.dataset.lastMqttValue = value; element.parentNode.getElementsByTagName('div')[0].classList.remove('loader'); break; case 'button': if (typeof value === 'object') return; element.classList.remove('working'); if (element.dataset.mqttValue === value) { element.classList.add('active'); } else { element.classList.remove('active'); } break; case 'number': if (isNaN(value)) return; element.value = value; element.style.width = (element.value.length + 2) + "ch"; element.classList.remove('working'); break; } }); }; const getConfig = async () => { const response = await fetch('/config.json'); if (!response.ok) { if (!localStorage.getItem('config')) return { pages: [{ pageid: "mainpage", pagetitle: "No Config!", sections: [] }] }; return JSON.parse(localStorage.getItem('config')); } const config = await response.json(); localStorage.setItem('config', JSON.stringify(config)); return config; }; const renderItem = (itemData) => { if (typeof itemData.topic === 'string') { const temporary = itemData.topic; itemData.topic = {}; itemData.topic.get = temporary; itemData.topic.set = null; } if (typeof itemData.topic === 'undefined') itemData.topic = {} let transform = null; if (typeof itemData.transform !== 'undefined') { if (typeof itemData.transform === 'string') transform = itemData.transform; if (typeof itemData.transform.get === 'string') transform = itemData.transform.get; }; if (itemData.type !== 'html') { let element = html``; switch (itemData.type) { case 'text': if (typeof itemData.topic === 'undefined') break; element = html``; break; case 'switch': const switchChangeHandler = (event) => { if (!client.connected) return false; if (itemData.topic.set === null) return false; client.publish(itemData.topic.set, transformMessage(event.target.checked, itemData), itemData.mqtt); return false; } element = html` `; break; case 'slider': const sliderChangeHandler = (event) => { if (!client.connected) return false; if (itemData.topic.set === null) return false; client.publish(itemData.topic.set, transformMessage(event.target.value, itemData), itemData.mqtt); } const sliderInputHandler = (event) => { if (!client.connected) return false; if (itemData.topic.set === null) return false; const element = event.target; const value = (element.dataset.lastMqttValue - element.value) / (element.max - element.min) * (element.getBoundingClientRect().width - 20); event.target.style.setProperty('--c', value + 'px'); } itemData.sliderMinValue ??= 0; itemData.sliderMaxValue ??= 1; itemData.sliderStepValue ??= 'any'; element = html``; break; case 'select': const selectChangeHandler = (event) => { if (!client.connected) return false; if (itemData.topic.set === null) return false const element = event.target; element.parentNode.getElementsByTagName('div')[0].classList.add('loader'); client.publish(itemData.topic.set, transformMessage(element.value, itemData), itemData.mqtt); // Reset to last known state element.value = element.dataset.lastMqttValue } element = html`
`; break; case 'button': const buttonClickHandler = (event) => { if (!client.connected) return false; if (itemData.topic.set === null) return false; event.target.classList.add('working'); client.publish(itemData.topic.set, transformMessage(event.target.dataset.mqttValue, itemData), itemData.mqtt); return false; } const buttonElement = (button) => html``; element = html` `; break; case 'number': const keydownHandler = (event) => { const element = event.target; element.style.width = (element.value.length + 2) + "ch"; if (event.code === 'Backspace') return true; if (event.code === 'Delete') return true; if (!(/^([.,0-9]+)$/.test(event.key))) { event.preventDefault(); return false; } } const numberHandlder = (event) => { if (!client.connected) return false; if (itemData.topic.set === null) return false; const input = event.target.parentNode.querySelector('input'); let inputValue = Number(input.value.replace(',', '.')); itemData.numberMinValue ??= 1; itemData.numberMaxValue ??= 254; itemData.numberIncrement ??= 1; itemData.numberDecrement ??= 1; if (event.target.textContent === '-') { if (inputValue === Number(itemData.numberMinValue)) return false; inputValue = inputValue - itemData.numberDecrement; } if (event.target.textContent === '+') { if (inputValue === Number(itemData.numberMaxValue)) return false; inputValue = inputValue + itemData.numberIncrement; } const transformedValue = transformMessage(inputValue, itemData); client.publish(itemData.topic.set, transformedValue, itemData.mqtt); input.classList.add('working'); } element = html`