changeset 2098:5f94c9f5b879

port ui to lit
author drewp@bigasterisk.com
date Tue, 31 May 2022 00:41:35 -0700
parents ffd0a84d54f2
children 5f0c2e350283
files light9/effect/sequencer/web/Light9SequencerUi.ts light9/effect/sequencer/web/index.html
diffstat 2 files changed, 156 insertions(+), 117 deletions(-) [+]
line wrap: on
line diff
--- a/light9/effect/sequencer/web/Light9SequencerUi.ts	Tue May 31 00:15:33 2022 -0700
+++ b/light9/effect/sequencer/web/Light9SequencerUi.ts	Tue May 31 00:41:35 2022 -0700
@@ -1,122 +1,161 @@
-<dom-module id="light9-sequencer-ui">
-<template>
-  <style>
-   :host {
-       display: block;
-   }
-   td {
-       white-space: nowrap;
-       padding: 0 10px;
-       vertical-align: top;
-       vertical-align: top;
-       text-align: start;
-   }
-   tr.active { background: #151515; }
-   .inactive > * { opacity: .5; }
-   .effectSetting {
-       display: inline-block;
-       background: #1b1e21;
-       margin: 1px 3px;
-   }
-   .chart {
-       height: 40px;
-       background: #222;
-       display: inline-flex;
-       align-items: flex-end;
-   }
-   .chart > div {
-       background: #a4a54f;
-       width: 8px;
-       margin: 0 1px;
-   }
-   .number {
-       display: inline-block;
-       min-width: 4em;
-   }
-  </style>
-  <rdfdb-synced-graph graph="{{graph}}"></rdfdb-synced-graph>
+import debug from "debug";
+import { css, html, LitElement } from "lit";
+import { customElement, property } from "lit/decorators.js";
+import { NamedNode } from "n3";
+import { getTopGraph } from "../../../web/RdfdbSyncedGraph";
+import { SyncedGraph } from "../../../web/SyncedGraph";
+
+debug.enable("*");
+const log = debug("sequencer");
 
-  <h1>Sequencer <a href="stats/">[stats]</a></h1>
-  
-  <h2>Song</h2>
-
-  <resource-display graph="{{graph}}" uri="{{report.song}}"></resource-display>
-  t={{report.roundT}}
-  
-  <h3>Notes</h3>
+interface Note {
+  note: string;
+  nonZero: boolean;
+  rowClass?: string; // added in message handler below
+  effectClass: string;
+  effectSettings: { [attr: string]: string };
+  effectSettingsPairs: EffectSettingsPair[]; // added in message handler below
+  devicesAffected: number;
+}
+interface Report {
+  song: string;
+  songUri: NamedNode; // added in message handler below
+  t: number;
+  roundT?: number; // added in message handler below
+  recentFps: number;
+  recentDeltas: number[];
+  recentDeltasStyle: string[]; // added in message handler below
+  songNotes: Note[];
+}
+interface EffectSettingsPair {
+  effectAttr: string;
+  value: any;
+}
+@customElement("light9-sequencer-ui")
+export class Light9SequencerUi extends LitElement {
+  static styles = [
+    css`
+      :host {
+        display: block;
+      }
+      td {
+        white-space: nowrap;
+        padding: 0 10px;
+        vertical-align: top;
+        vertical-align: top;
+        text-align: start;
+      }
+      tr.active {
+        background: #151515;
+      }
+      .inactive > * {
+        opacity: 0.5;
+      }
+      .effectSetting {
+        display: inline-block;
+        background: #1b1e21;
+        margin: 1px 3px;
+      }
+      .chart {
+        height: 40px;
+        background: #222;
+        display: inline-flex;
+        align-items: flex-end;
+      }
+      .chart > div {
+        background: #a4a54f;
+        width: 8px;
+        margin: 0 1px;
+      }
+      .number {
+        display: inline-block;
+        min-width: 4em;
+      }
+    `,
+  ];
+  render() {
+    return html`
+      <rdfdb-synced-graph></rdfdb-synced-graph>
 
-  <table>
-    <tr>
-      <th>Note</th>
-      <th>Effect class</th>
-      <th>Effect settings</th>
-      <th>Devices affected</th>
-    </tr>
-    <template is="dom-repeat" items="{{report.songNotes}}">
+      <h1>Sequencer <a href="metrics/">[metrics]</a></h1>
 
-      <tr class$="{{item.rowClass}}">
-        <td>
-          <resource-display graph="{{graph}}" uri="{{item.note}}"></resource-display>
-        </td>
-        <td>
-          <resource-display graph="{{graph}}" uri="{{item.effectClass}}"></resource-display>
-        </td>  
-        <td>
-          <template is="dom-repeat" items="{{item.effectSettingsPairs}}">
-            <div>
-            <span class="effectSetting">
-              <resource-display graph="{{graph}}" uri="{{item.effectAttr}}"></resource-display>:
-              <span class="number">{{item.value}}</span>
-            </span>
-            </div>
-          </template>
-        </td>
-        <td>
-          {{item.devicesAffected}}
-        </td>
-      </tr>
-    </template>
-  </table>
+      <h2>Song</h2>
+
+      <resource-display uri=${this.report.songUri}"></resource-display>
+      t=${this.report.roundT}
+
+      <h3>Notes</h3>
+
+      <table>
+        <tr>
+          <th>Note</th>
+          <th>Effect class</th>
+          <th>Effect settings</th>
+          <th>Devices affected</th>
+        </tr>
+        ${this.report.songNotes.map(
+          (item: Note) => html`
+            <tr class$="${item.rowClass}">
+              <td><resource-display uri="${item.note}"></resource-display></td>
+              <td><resource-display uri="${item.effectClass}"></resource-display></td>
+              <td>
+                ${item.effectSettingsPairs.map(
+                  (item) => html`
+                    <div>
+                      <span class="effectSetting">
+                        <resource-display uri="${item.effectAttr}"></resource-display>:
+                        <span class="number">${item.value}</span>
+                      </span>
+                    </div>
+                  `
+                )}
+              </td>
+              <td>${item.devicesAffected}</td>
+            </tr>
+          `
+        )}
+      </table>
+    `;
+  }
 
-</template>
-<script>
- HTMLImports.whenReady(function () {
-   Polymer({
-     is: "light9-sequencer-ui",
-     properties: {
-       graph: {type: Object, notify: true},
-       report: {type: Object, notify: true},
-     },
-     ready: function() {
-       var source = new EventSource('updates');
-       source.addEventListener('message', (e) => {
-         const report = JSON.parse(e.data);
-         report.roundT = Math.floor((report.t || 0) * 1000) / 1000;
-         report.recentFps = Math.floor((report.recentFps || 0) * 10) / 10;
-         report.recentDeltasStyle = (report.recentDeltas || []).map((dt) => {
-           const height = Math.min(40, dt / 0.085 * 20);
-           return `height: ${height}px;`
-         });
+  graph!: SyncedGraph;
+  @property() report!: Report;
+
+  constructor() {
+    super();
+    getTopGraph().then((g) => {
+      var source = new EventSource("./api/updates");
+      source.addEventListener("message", this.onMessage.bind(this));
+    });
+  }
+  onMessage(ev: MessageEvent) {
+    const report = JSON.parse(ev.data) as Report;
+    report.roundT = Math.floor((report.t || 0) * 1000) / 1000;
+    report.recentFps = Math.floor((report.recentFps || 0) * 10) / 10;
+    report.recentDeltasStyle = (report.recentDeltas || []).map((dt) => {
+      const height = Math.min(40, (dt / 0.085) * 20);
+      return `height: ${height}px;`;
+    });
+    report.songUri = this.graph.Uri(report.song);
 
-         const fakeUris = (report.songNotes || []).map((obj) => { return {value: obj.note, orig: obj} });
-         const s = this.graph.sortedUris(fakeUris);
-         report.songNotes = s.map((u) => { return u.orig; });
-         
-         (report.songNotes || []).forEach((note) => {
-           note.rowClass = note.nonZero ? 'active' : 'inactive';
-           note.effectSettingsPairs = [];
+    const fakeUris = (report.songNotes || []).map((obj) => {
+      return { value: obj.note, orig: obj };
+    });
+    const s = this.graph.sortedUris(fakeUris);
+    report.songNotes = s.map((u) => {
+      return u.orig;
+    });
 
-           const attrs = Object.keys(note.effectSettings);
-           attrs.sort();
-           attrs.forEach((attr) => {
-             note.effectSettingsPairs.push(
-               {effectAttr: attr, value: note.effectSettings[attr]});
-           });
-         });
-         this.report = report;
-       });
-     },
-   });
- });
-</script>
-</dom-module>
+    (report.songNotes || []).forEach((note) => {
+      note.rowClass = note.nonZero ? "active" : "inactive";
+      note.effectSettingsPairs = [];
+
+      const attrs = Object.keys(note.effectSettings);
+      attrs.sort();
+      attrs.forEach((attr) => {
+        note.effectSettingsPairs.push({ effectAttr: attr, value: note.effectSettings[attr] } as EffectSettingsPair);
+      });
+    });
+    this.report = report;
+  }
+}
--- a/light9/effect/sequencer/web/index.html	Tue May 31 00:15:33 2022 -0700
+++ b/light9/effect/sequencer/web/index.html	Tue May 31 00:41:35 2022 -0700
@@ -5,7 +5,7 @@
     <meta charset="utf-8" />
 
     <link rel="stylesheet" href="./style.css" />
-    <script type="module" src="./Light9SequencerUi"></script>
+    <script type="module" src="../effectSequencer/Light9SequencerUi"></script>
   </head>
   <body>
     <light9-sequencer-ui></light9-sequencer-ui>