view src/main.ts @ 9:9f427d8073c3

redo data model; add ui colors
author drewp@bigasterisk.com
date Sun, 28 Jan 2024 16:53:08 -0800
parents c04563fc8616
children 028ed39aa78f
line wrap: on
line source

import { LitElement, css, html } from "lit";
import { customElement, state } from "lit/decorators.js";

@customElement("lb-page")
export class LbPage extends LitElement {
  static styles = [
    css`
      :host {
        display: flex;
        flex-direction: column;
        height: 100vh;
      }
      table {
        border-collapse: collapse;
      }
      td,
      th {
        border: 1px solid #aaa;
        text-align: center;
      }
      .color {
        display: inline-block;
        width: 30px;
        height: 30px;
        border-radius: 50%;
        margin: 3px;
        vertical-align: middle;
      }
      .col-group-1 {
        background: #e0ecf4;
      }
      .col-group-2 {
        background: #e0f3db;
      }
      .col-group-3 {
        background: #fee8c8;
      }
    `,
  ];

  // bug https://github.com/lit/lit/issues/4305
  @((state as any)()) lights: object[] = [];
  @((state as any)()) reportTime: Date = new Date(0);

  connectedCallback(): void {
    super.connectedCallback();
    const es = new EventSource("api/table");
    es.onmessage = (ev) => {
      const body = JSON.parse(ev.data);
      this.lights = body.lights;
      this.reportTime = new Date(body.now * 1000);
    };
  }
  render() {
    return html`
      <h1>Light-bridge</h1>

      <table>
        <tr>
          <th class="col-group-1">light</th>
          <th class="col-group-1">address</th>
          <th class="col-group-2">requested color</th>
          <th class="col-group-2">requested device color</th>
          <th class="col-group-3">emitting color</th>
          <th class="col-group-3">online</th>
          <th class="col-group-3">latency</th>
        </tr>
        ${this.lights.map(
          (d: any) => html`
            <tr>
              <td class="col-group-1">${d.light.name}</td>
              <td class="col-group-1"><code>${d.light.address}</code></td>
              <td class="col-group-2">
                <code>${d.light.requestingColor}</code>
                <input type="color" @input=${this.onRequestingColor.bind(this, d.light.name)} .value="${d.light.requestingColor}" />
              </td>
              <td class="col-group-2"><code>${JSON.stringify(d.light.requestingDeviceColor)}</code></td>
              <td class="col-group-3">${d.light.emittingColor} <span class="color" style="background: ${d.light.emittingColor}"></span></td>
              <td class="col-group-3">${d.light.online ? "✔" : ""}</td>
              <td class="col-group-3">${d.light.latencyMs} ms</td>
            </tr>
          `
        )}
      </table>
      <p>Updated ${this.reportTime.toLocaleString("sv")}</p>
      <p>
        <a href="metrics">metrics</a> |
        <a href="api/graph">graph</a>
      </p>
      <bigast-loginbar></bigast-loginbar>
    `;
  }
  onRequestingColor(lightName: string, ev: InputEvent) {
    const value = (ev.target as HTMLInputElement).value;
    const url = new URL("api/output", location as any);
    url.searchParams.append("light", lightName);
    fetch(url, { method: "PUT", body: value }); // todo: only run one fetch at a time, per light
  }
}