0
|
1 import { LitElement, css, html } from "lit";
|
|
2 import { customElement, state } from "lit/decorators.js";
|
|
3
|
|
4 @customElement("lb-page")
|
|
5 export class LbPage extends LitElement {
|
|
6 static styles = [
|
|
7 css`
|
|
8 :host {
|
|
9 display: flex;
|
|
10 flex-direction: column;
|
|
11 height: 100vh;
|
|
12 }
|
|
13 table {
|
|
14 border-collapse: collapse;
|
|
15 }
|
|
16 td,
|
|
17 th {
|
|
18 border: 1px solid #aaa;
|
|
19 text-align: center;
|
|
20 }
|
|
21 .color {
|
|
22 display: inline-block;
|
|
23 width: 30px;
|
|
24 height: 30px;
|
|
25 border-radius: 50%;
|
|
26 margin: 3px;
|
|
27 vertical-align: middle;
|
|
28 }
|
9
|
29 .col-group-1 {
|
|
30 background: #e0ecf4;
|
|
31 }
|
|
32 .col-group-2 {
|
|
33 background: #e0f3db;
|
|
34 }
|
|
35 .col-group-3 {
|
|
36 background: #fee8c8;
|
|
37 }
|
0
|
38 `,
|
|
39 ];
|
3
|
40
|
|
41 // bug https://github.com/lit/lit/issues/4305
|
9
|
42 @((state as any)()) lights: object[] = [];
|
|
43 @((state as any)()) reportTime: Date = new Date(0);
|
0
|
44
|
|
45 connectedCallback(): void {
|
|
46 super.connectedCallback();
|
|
47 const es = new EventSource("api/table");
|
|
48 es.onmessage = (ev) => {
|
1
|
49 const body = JSON.parse(ev.data);
|
|
50 this.lights = body.lights;
|
|
51 this.reportTime = new Date(body.now * 1000);
|
0
|
52 };
|
|
53 }
|
|
54 render() {
|
|
55 return html`
|
|
56 <h1>Light-bridge</h1>
|
|
57
|
|
58 <table>
|
|
59 <tr>
|
9
|
60 <th class="col-group-1">light</th>
|
|
61 <th class="col-group-1">address</th>
|
|
62 <th class="col-group-2">requested color</th>
|
|
63 <th class="col-group-2">requested device color</th>
|
|
64 <th class="col-group-3">emitting color</th>
|
|
65 <th class="col-group-3">online</th>
|
|
66 <th class="col-group-3">latency</th>
|
0
|
67 </tr>
|
|
68 ${this.lights.map(
|
|
69 (d: any) => html`
|
|
70 <tr>
|
9
|
71 <td class="col-group-1">${d.light.name}</td>
|
|
72 <td class="col-group-1"><code>${d.light.address}</code></td>
|
|
73 <td class="col-group-2">
|
|
74 <code>${d.light.requestingColor}</code>
|
|
75 <input type="color" @input=${this.onRequestingColor.bind(this, d.light.name)} .value="${d.light.requestingColor}" />
|
0
|
76 </td>
|
9
|
77 <td class="col-group-2"><code>${JSON.stringify(d.light.requestingDeviceColor)}</code></td>
|
|
78 <td class="col-group-3">${d.light.emittingColor} <span class="color" style="background: ${d.light.emittingColor}"></span></td>
|
|
79 <td class="col-group-3">${d.light.online ? "✔" : ""}</td>
|
|
80 <td class="col-group-3">${d.light.latencyMs} ms</td>
|
0
|
81 </tr>
|
|
82 `
|
|
83 )}
|
|
84 </table>
|
1
|
85 <p>Updated ${this.reportTime.toLocaleString("sv")}</p>
|
0
|
86 <p>
|
|
87 <a href="metrics">metrics</a> |
|
|
88 <a href="api/graph">graph</a>
|
|
89 </p>
|
|
90 <bigast-loginbar></bigast-loginbar>
|
|
91 `;
|
|
92 }
|
9
|
93 onRequestingColor(lightName: string, ev: InputEvent) {
|
0
|
94 const value = (ev.target as HTMLInputElement).value;
|
|
95 const url = new URL("api/output", location as any);
|
|
96 url.searchParams.append("light", lightName);
|
|
97 fetch(url, { method: "PUT", body: value }); // todo: only run one fetch at a time, per light
|
|
98 }
|
|
99 }
|