Mercurial > code > home > repos > streamed-graph
view src/render/GraphView.ts @ 118:c2923b20bf5c
support multi labels per column
author | drewp@bigasterisk.com |
---|---|
date | Sun, 20 Mar 2022 00:54:19 -0700 |
parents | 4822d5621463 |
children |
line wrap: on
line source
import Immutable from "immutable"; import { html, TemplateResult } from "lit"; import { NamedNode, Quad, Store, Term } from "n3"; import { AlignedTable, FreeStatements, Layout, PredRow, SubjRow, } from "../layout/Layout"; import { uniqueSortedTerms } from "../layout/rdf_value"; import { SuffixLabels } from "../layout/suffixLabels"; import { ViewConfig } from "../layout/ViewConfig"; import { NodeDisplay } from "./NodeDisplay"; type UriSet = Immutable.Set<NamedNode>; export class GraphView { nodeDisplay!: NodeDisplay; constructor( public dataSourceUrls: string[], public graph: Store, public viewConfig?: ViewConfig ) {} async makeTemplate(): Promise<TemplateResult> { const layout = new Layout(this.viewConfig); const lr = layout.plan(this.graph); const labels = new SuffixLabels(); this._addLabelsForAllTerms(this.graph, labels); this.nodeDisplay = new NodeDisplay(labels); let viewTitle = html` (no view)`; if (this.viewConfig?.url) { viewTitle = html` using view <a href="${this.viewConfig?.url}">${this.viewConfig?.label()}</a>`; } return html` <section> <h2> Current graph (<a href="${this.dataSourceUrls[0]}" >${this.dataSourceUrls[0]}</a >)${viewTitle} </h2> <div> <!-- todo: graphs and provenance. These statements are all in the <span data-bind="html: $root.createCurie(graphUri())">...</span> graph.--> </div> ${lr.sections.map(this._renderSection.bind(this))} </section> `; } _addLabelsForAllTerms(graph: Store, labels: SuffixLabels) { graph.forEach( (q: Quad) => { if (q.subject.termType === "NamedNode") { labels.planDisplayForNode(q.subject); } if (q.predicate.termType === "NamedNode") { labels.planDisplayForNode(q.predicate); } if (q.object.termType === "NamedNode") { labels.planDisplayForNode(q.object); } if (q.object.termType === "Literal" && q.object.datatype) { labels.planDisplayForNode(q.object.datatype); } }, null, null, null, null ); } _renderSection(section: AlignedTable | FreeStatements) { if ((section as any).columnHeaders) { return this._renderAlignedTable(section as AlignedTable); } else { return this._renderFreeStatements(section as FreeStatements); } } _renderAlignedTable(section: AlignedTable): TemplateResult { const tableTypes: NamedNode[][] = []; const typeHeads: TemplateResult[] = []; const heads: TemplateResult[] = []; for (let ch of section.columnHeaders) { const colSpan = 1; //todo typeHeads.push( html`<th colspan="${colSpan}"> ${ch.rdfTypes.map((n) => this.nodeDisplay.render(n))} </th>` ); tableTypes.push(ch.rdfTypes); heads.push(html`<th>${this.nodeDisplay.render(ch.pred)}</th>`); } const cells = []; for (let rowIndex in section.rows) { const headerCol = this.nodeDisplay.render(section.rowHeaders[rowIndex]); const bodyCols = []; for (let cellObjs of section.rows[rowIndex]) { const display = cellObjs.map( (t) => html`<div>${this.nodeDisplay.render(t)}</div>` ); bodyCols.push(html`<td>${display}</td>`); } cells.push( html`<tr> <th>${headerCol}</th> ${bodyCols} </tr>` ); } const tableTypesUnique = uniqueSortedTerms(tableTypes.flat()); const typesDisplay = html`${tableTypesUnique.length == 1 ? "type" : "types"} ${tableTypesUnique.map((n) => this.nodeDisplay.render(n))}`; return html` <div>[icon] Resources of ${typesDisplay}</div> <div class="typeBlockScroll"> <table class="typeBlock"> <thead> <tr> <th></th> ${typeHeads} </tr> <tr> <th>Subject</th> ${heads} </tr> </thead> <tbody> ${cells} </tbody> </table> </div> `; } _renderFreeStatements(section: FreeStatements): TemplateResult { const subjects: NamedNode[] = []; let subjPreds = Immutable.Map<NamedNode, UriSet>(); return html`<div class="spoGrid"> grid has rowcount ${section.subjRows.length} ${section.subjRows.map(this._subjPredObjsBlock.bind(this))} </div>`; } _subjPredObjsBlock(row: SubjRow): TemplateResult { return html` <div class="subject"> ${this.nodeDisplay.render(row.subj)} <!-- todo: special section for uri/type-and-icon/label/comment --> <div>${row.predRows.map(this._predObjsBlock.bind(this))}</div> </div> `; } _predObjsBlock(row: PredRow): TemplateResult { return html` <div class="predicate"> ${this.nodeDisplay.render(row.pred)} <div>${row.objs.map(this._objCell.bind(this))}</div> </div> `; } _objCell(obj: Term): TemplateResult { return html` <div class="object"> ${this.nodeDisplay.render(obj)} <!-- indicate what source or graph said this stmt --> </div> `; } _drawObj(obj: Term): TemplateResult { return html` <div>${this.nodeDisplay.render(obj)}</div> `; } _drawColumnHead(pred: NamedNode): TemplateResult { return html` <th>${this.nodeDisplay.render(pred)}</th> `; } // return html` // <div>[icon] Resources of type ${typeNames}</div> // <div class="typeBlockScroll"> // <table class="typeBlock"> // ${this._thead(layout)} ${layout.subjs.map(this._instanceRow(layout))} // </table> // </div> // `; // } }