comparison src/index.ts @ 106:2468f2227d22

make src/layout/ and src/render/ separation
author drewp@bigasterisk.com
date Sun, 13 Mar 2022 22:00:30 -0700
parents 955cde1550c3
children 042bd3361339
comparison
equal deleted inserted replaced
105:4bb8c7775c83 106:2468f2227d22
1 import { LitElement, html, render, TemplateResult } from "lit"; 1 import { StreamedGraph } from "./render/element";
2 import { customElement, property } from "lit/decorators.js";
3 2
4 import { Store } from "n3"; 3 export {StreamedGraph}
5
6 import { GraphView } from "./graph_view";
7 import { StreamedGraphClient } from "./streamed_graph_client";
8 import { style, addFontToRootPage } from "./style";
9
10 // export * from "./graph_queries";
11
12 export interface VersionedGraph {
13 version: number;
14 store: Store;
15 }
16
17 @customElement("streamed-graph")
18 export class StreamedGraph extends LitElement {
19 @property({ type: String })
20 url: string = "";
21 @property({ type: String })
22 view: string = "";
23 @property({ type: Object })
24 graph!: VersionedGraph;
25
26 @property({ type: Boolean })
27 expanded: boolean = false;
28
29 @property({ type: String })
30 status: string = "";
31
32 sg!: StreamedGraphClient;
33 graphViewDirty = true;
34
35 static styles = style;
36
37 render() {
38 const expandAction = this.expanded ? "-" : "+";
39 return html`
40 <div id="ui">
41 <span class="expander"
42 ><button @click="${this.toggleExpand}">${expandAction}</button></span
43 >
44 StreamedGraph <a href="${this.url}">[source]</a>: ${this.status}
45 </div>
46 <div id="graphView"></div>
47 `;
48 }
49
50 connectedCallback() {
51 super.connectedCallback();
52 addFontToRootPage();
53 const emptyStore = new Store();
54 this.graph = { version: -1, store: emptyStore };
55
56 this._onUrl(this.url); // todo: watch for changes and rebuild
57 if (this.expanded) {
58 this.redrawGraph();
59 }
60 }
61
62 toggleExpand() {
63 this.expanded = !this.expanded;
64 if (this.expanded) {
65 this.redrawGraph();
66 } else {
67 this.graphViewDirty = false;
68 this._graphAreaClose();
69 }
70 }
71
72 redrawGraph() {
73 this.graphViewDirty = true;
74 const rl: ()=>Promise<void> = this._redrawLater.bind(this)
75 requestAnimationFrame(rl);
76 }
77
78 _onUrl(url: string) {
79 if (this.sg) {
80 this.sg.close();
81 }
82 this.sg = new StreamedGraphClient(
83 url,
84 this.onGraphChanged.bind(this),
85 (st) => {
86 this.status = st;
87 },
88 [], //window.NS,
89 []
90 );
91 }
92
93 onGraphChanged() {
94 this.graph = {
95 version: this.graph.version + 1,
96 store: this.sg.store,
97 };
98 if (this.expanded) {
99 this.redrawGraph();
100 }
101 this.dispatchEvent(
102 new CustomEvent("graph-changed", { detail: { graph: this.graph } })
103 );
104 }
105
106 async _redrawLater() {
107 if (!this.graphViewDirty) return;
108
109 if ((this.graph as VersionedGraph).store && this.graph.store) {
110 await this._graphAreaShowGraph(
111 new GraphView(this.url, this.view, this.graph.store)
112 );
113 this.graphViewDirty = false;
114 } else {
115 this._graphAreaShowPending();
116 }
117 }
118
119 _graphAreaClose() {
120 this._setGraphArea(html``);
121 }
122
123 _graphAreaShowPending() {
124 this._setGraphArea(html` <span>waiting for data...</span> `);
125 }
126
127 async _graphAreaShowGraph(graphView: GraphView) {
128 this._setGraphArea(await graphView.makeTemplate());
129 }
130
131 _setGraphArea(tmpl: TemplateResult) {
132 const el = this.shadowRoot?.getElementById("graphView");
133 if (!el) {
134 return;
135 }
136 render(tmpl, el);
137 }
138 }
139
140 declare global {
141 interface HTMLElementTagNameMap {
142 "streamed-graph": StreamedGraph;
143 }
144 }
145
146 // // allow child nodes to combine a few graphs and statics
147 // //<streamed-graph id="timebankGraph" graph="{{graph}}" expanded="true">
148 // // <member-graph url="graph/timebank/events"></member-graph>
149 // // <member-graph url="/some/static.n3"></member-graph>
150 // //</streamed-graph>