commit b858973727982e30aa5c7505ff1930a70bd1435c
parent 40386c4cb34c20d25b85675f7bb66705df26ca05
Author: Milan Pässler <me@pbb.lc>
Date: Thu, 20 Jun 2019 10:50:05 +0200
parent 40386c4cb34c20d25b85675f7bb66705df26ca05
Author: Milan Pässler <me@pbb.lc>
Date: Thu, 20 Jun 2019 10:50:05 +0200
history loading spinner and more
9 files changed, 62 insertions(+), 49 deletions(-)
diff --git a/index.dev.html b/index.dev.html @@ -15,6 +15,6 @@ body { <body> <smarthome-layout></smarthome-layout> <noscript>JavaScript is required to use Smart Home</noscript> - <script type="module" src="main.min.js"></script> + <script type="module" src="main.js"></script> </body> </html>
diff --git a/src/archive.js b/src/archive.js @@ -2,11 +2,16 @@ class Archive { constructor() { - this.archive = {}; + this.data = JSON.parse(localStorage.getItem("archive") || "{}");; this._loading = {}; + this._upToDate = {}; this._subscribers = []; } + finishedLoading() { + return Object.keys(this._loading).length == 0; + } + subscribe(callback) { this._subscribers.push(callback); this._updateSubscribers(); @@ -19,19 +24,19 @@ class Archive { } load(file) { - if (!this.archive[file]) { + if (!this.data[file] || !this._upToDate[file]) { this._loading[file] = true; - const p = fetch(`archive/${file}.json`) + fetch(`./archive/${file}.json`) .then(resp => resp.json()) .then(data => { - this.archive[file] = data; - this._loading[file] = undefined; + this.data[file] = data; + this._upToDate[file] = true; + localStorage.setItem("archive", JSON.stringify(this.data)); + delete this._loading[file]; this._updateSubscribers(); - return data; - }).catch(e => console.warn(e)); - return {}; - } else { - return this.archive[file]; + }).catch(e => { + console.warn(e); + }); } } }
diff --git a/src/departures.js b/src/departures.js @@ -64,7 +64,7 @@ class Departures extends LitElement { </smarthome-card> `)} ` : html` - <smarthome-spinner></smarthome-spinner> + <smarthome-spinner>Loading...</smarthome-spinner> `} `; }
diff --git a/src/layout.js b/src/layout.js @@ -22,7 +22,7 @@ const pages = { "#/lights": { name: "Lights", content: html`<smarthome-lights></smarthome-lights>`, icon: "lightbulb" }, "#/powermeter": { name: "Power Meter", content: html`<smarthome-power-meter></smarthome-power-meter>`, icon: "power" }, "#/departures": { name: "Departures", content: html`<smarthome-departures></smarthome-departures>`, icon: "departure_board" }, - "#/netdata": { name: "netdata", content: html`<smarthome-spinner></smarthome-spinner> ${netdataRedirect}`, icon: "show_chart" }, + "#/netdata": { name: "netdata", content: html`<smarthome-spinner>Redirecting...</smarthome-spinner> ${netdataRedirect}`, icon: "show_chart" }, "#/settings": { name: "Settings", content: html`<smarthome-settings></smarthome-settings>`, icon: "settings" }, };
diff --git a/src/lights.js b/src/lights.js @@ -40,7 +40,7 @@ class Lights extends LitElement { `)} </smarthome-card> ` : html` - <smarthome-spinner></smarthome-spinner> + <smarthome-spinner>Trying to connect...</smarthome-spinner> `} `; }
diff --git a/src/power-meter/history.js b/src/power-meter/history.js @@ -37,41 +37,42 @@ class PowerMeterHistory extends LitElement { const now = new Date(); this.year = now.getFullYear(); this.month = pad(now.getMonth() + 1, 2); + this.data = {}; - state.subscribe(this.loadData.bind(this)); - archive.subscribe(this.loadData.bind(this)); - } - - async loadData(e) { - const d = {}; - - this.sel = this.year; - if (this.type === "day") this.sel += "_" + this.month; - - await Promise.all(Object.entries(state.data.powermeter).map(async ([id, p]) => { - const data = await archive.load(`${this.type}/${id}_${this.sel}`); - if(!data) return; - for (let day of Object.keys(data)) { - if (!d[day]) d[day] = {}; - d[day][id] = data[day].imported; - } - })); - this.data = d; - - this.requestUpdate(); + state.subscribe(this.requestUpdate.bind(this)); + archive.subscribe(this.requestUpdate.bind(this)); } handleSelected(field) { return (evt) => { this[field] = evt.detail.item.value; - this.loadData(); + this.requestUpdate(); }; } render() { const now = new Date(); + + this.data = {}; + this.sel = this.year; + if (this.type === "day") this.sel += "_" + this.month; + + archive.load("metadata"); + const years = get(archive.data, [ "metadata", "availableData" ], {}); + const months = get(archive.data, [ "metadata", "availableData", this.year ], []); + const counters = get(archive.data, [ "metadata", "meters" ], {}); + + for (let [id, p] of Object.entries(counters)) { + archive.load(`${this.type}/${id}_${this.sel}`); + const data = get(archive.data, [ `${this.type}/${id}_${this.sel}` ], {}); + for (let day of Object.keys(data)) { + if (!this.data[day]) this.data[day] = {}; + this.data[day][id] = data[day].imported; + } + } + return html` - <div id="selection" class="${state.data.powermeter && state.connected ? "" : "hidden"}"> + <div id="selection" class="${Object.keys(years).length > 0 ? "" : "hidden"}"> <mwc-select label="Type"> <mwc-menu slot="menu" class="type-sel" @MDCMenu:selected=${this.handleSelected("type")}> <mwc-list> @@ -84,19 +85,19 @@ class PowerMeterHistory extends LitElement { <mwc-select label="Year"> <mwc-menu slot="menu" class="year-sel" @MDCMenu:selected=${this.handleSelected("year")}> <mwc-list> - ${Object.keys(get(archive.load("metadata"), [ "availableData" ], {})).map(m => html`<mwc-list-item value="${m}">${m}</mwc-list-item>`)} + ${Object.keys(years).map(m => html`<mwc-list-item value="${m}">${m}</mwc-list-item>`)} </mwc-list> </mwc-menu> </mwc-select> <mwc-select label="Month" class="${this.type == "day" ? "" : "hidden"}"> <mwc-menu slot="menu" class="month-sel" @MDCMenu:selected=${this.handleSelected("month")}> <mwc-list> - ${get(archive.load("metadata"), [ "availableData", this.year ], []).map(m => html`<mwc-list-item value="${m}">${Number(m)}</mwc-list-item>`)} + ${months.map(m => html`<mwc-list-item value="${m}">${Number(m)}</mwc-list-item>`)} </mwc-list> </mwc-menu> </mwc-select> </div> - ${state.data.powermeter && state.connected ? html` + ${archive.finishedLoading() ? html` <smarthome-card> <div class="table"> <div class="table-row table-head"> @@ -105,9 +106,9 @@ class PowerMeterHistory extends LitElement { <div class="table-column">${formatName(this.type, day)}</table-column> `)} </div> - ${Object.entries(state.data.powermeter).map(([id, d]) => html` + ${Object.entries(counters).map(([id, name]) => html` <div class="table-row"> - <div class="table-column">${d.name}</div> + <div class="table-column">${name}</div> ${Object.entries(this.data).reverse().map(([day, d]) => html` <div class="table-column">${d[id] ? round(d[id], 2) + " kWh" : "-"}</div> `)} @@ -115,7 +116,9 @@ class PowerMeterHistory extends LitElement { `)} </div> </smarthome-card> - ` : html``} + ` : html` + <smarthome-spinner>Loading...</smarthome-spinner> + `} `; }
diff --git a/src/power-meter/live.js b/src/power-meter/live.js @@ -12,15 +12,20 @@ import "../spinner.js"; class PowerMeterLive extends LitElement { constructor() { super(...arguments); + this._cachedDayArchive = {}; state.subscribe(this.requestUpdate.bind(this)); archive.subscribe(this.requestUpdate.bind(this)); } getImport(id) { + const currentValue = state.data.powermeter[id].values.import; const now = new Date(); - const file = archive.load(`day/${id}_${now.getFullYear()}_${pad(now.getMonth() + 1, 2)}`); - const value = get(file, [ `${now.getFullYear()}${pad(now.getMonth() + 1, 2)}${pad(now.getDate(), 2)}`, "imported" ]); - return value ? round(value, 2) + " kWh" : "-"; + const filename = `day/${id}_${now.getFullYear()}_${pad(now.getMonth() + 1, 2)}`; + if (this._cachedDayArchive[filename] !== now.getDate()) delete archive.data[filename]; + archive.load(`day/${id}_${now.getFullYear()}_${pad(now.getMonth() + 1, 2)}`); + this._cachedDayArchive[filename] = now.getDate(); + const lastValue = get(archive.data, [filename, `${now.getFullYear()}${pad(now.getMonth() + 1, 2)}${pad(now.getDate() - 1, 2)}`, "totalImported" ]); + return currentValue && lastValue ? round(currentValue - lastValue, 2) + " kWh" : "-"; } render() { @@ -59,7 +64,7 @@ class PowerMeterLive extends LitElement { </div> </smarthome-card> ` : html` - <smarthome-spinner></smarthome-spinner> + <smarthome-spinner>Trying to connect...</smarthome-spinner> `} `; }
diff --git a/src/spinner.js b/src/spinner.js @@ -7,7 +7,7 @@ import "@authentic/mwc-circular-progress"; class Spinner extends LitElement { render() { return html` - <h3>Trying to connect...</h3> + <h3><slot></slot></h3> <mwc-circular-progress></mwc-circular-progress> `; }
diff --git a/src/state.js b/src/state.js @@ -28,7 +28,7 @@ class State { } _initWS() { - this.ws = new WebSocket(`${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.hostname}/${window.location.pathname}/ws`); + this.ws = new WebSocket(`${window.location.protocol === "https:" ? "wss" : "ws"}://${window.location.hostname}/${window.location.pathname.split("/").slice(0, -1).join("/")}/ws`); this.ws.onclose = () => { this.connected = false; this._initWS();