import debug from "debug"; import * as FlexLayout from "flexlayout-react"; import { LitElement, TemplateResult, html } from "lit"; import { customElement } from "lit/decorators.js"; import * as React from "react"; import { createRoot } from "react-dom/client"; import { getTopGraph } from "./RdfdbSyncedGraph"; import { SyncedGraph } from "./SyncedGraph"; import { panelDisplayName, panelElementNames, panelUrl } from "./panels"; export { RdfdbSyncedGraph } from "./RdfdbSyncedGraph"; const log = debug("home"); // see https://github.com/lit/lit/tree/main/packages/labs/react // Store flexlayout panels in per-browser localstorage. class PersistentLayout { key = "light9.home.layout"; defaultLayout: FlexLayout.IJsonRowNode = { type: "row", children: [ { type: "tabset", weight: 50, children: [{ type: "tab", name: "fade", component: "light9-fade-ui" }], }, { type: "tabset", weight: 50, children: [{ type: "tab", name: "devsettings", component: "light9-device-settings" }], }, ], }; getOrDefault(): FlexLayout.IJsonRowNode { let savedLayout = localStorage.getItem(this.key); if (savedLayout === null) { return this.defaultLayout; } return JSON.parse(savedLayout); } save(layout: FlexLayout.IJsonRowNode) { localStorage.setItem(this.key, JSON.stringify(layout)); } } // This lets lit call a method on a react element. let addTab: (component: string) => void; class Main extends React.Component { state: { model: FlexLayout.Model; persistence: PersistentLayout }; constructor(props: any) { super(props); const persistence = new PersistentLayout(); const config = { global: { tabEnableRename: false, }, borders: [], layout: persistence.getOrDefault(), }; this.state = { model: FlexLayout.Model.fromJson(config), persistence: persistence }; } factory = (node: any) => { var component = node.getComponent(); return React.createElement(component, null, ""); }; render() { addTab = (component) => { const name = panelDisplayName(component); if (name === undefined) throw new Error("no such panel: " + component); const newTab = { type: "tab", name: name, component: component }; const firstTabSet = this.state.model.getRoot().getChildren()[0]; const action = FlexLayout.Actions.addNode(newTab, firstTabSet.getId(), FlexLayout.DockLocation.LEFT, 0); this.state.model.doAction(action); }; return React.createElement(FlexLayout.Layout, { model: this.state.model, realtimeResize: true, onModelChange: this.onModelChange.bind(this), factory: this.factory, }); } onModelChange() { this.state.persistence.save(this.state.model.toJson().layout); } } @customElement("light9-home-status") export class Light9HomeStatus extends LitElement { graph!: SyncedGraph; render() { return html` metrics Open tab or new window: ${panelElementNames().map((elem) => this.linkToPanelPage(elem))} `; } linkToPanelPage(elem: string): TemplateResult { return html` ${panelDisplayName(elem)} `; } constructor() { super(); getTopGraph().then((g) => { this.graph = g; }); } onClickPanelLink(ev: MouseEvent) { ev.preventDefault(); const a = ev.target as HTMLAnchorElement; const elem = a.dataset.panelElem!; addTab(elem); } } const root = createRoot(document.getElementById("container")!); root.render(React.createElement(Main));