Mercurial > code > home > repos > streamed-graph
changeset 97:26c55d5d5202
WIP on views & joins
author | drewp@bigasterisk.com |
---|---|
date | Fri, 11 Feb 2022 20:27:02 -0800 |
parents | 4d19759d0d9a |
children | 6807ee85d031 |
files | demo/public/repos.n3 src/graph_view.ts src/suffixLabels.ts src/tabulate.ts src/view_loader.ts |
diffstat | 5 files changed, 57 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/demo/public/repos.n3 Thu Jan 13 21:32:18 2022 -0800 +++ b/demo/public/repos.n3 Fri Feb 11 20:27:02 2022 -0800 @@ -5,4 +5,7 @@ <> a :View ; rdfs:label "repos" . <> :table demo:table1 . -demo:table1 :showsType :Repo . +demo:table1 + :primaryType :Repo; + :joinType :HgRepo; + :joinType :GithubRepo .
--- a/src/graph_view.ts Thu Jan 13 21:32:18 2022 -0800 +++ b/src/graph_view.ts Fri Feb 11 20:27:02 2022 -0800 @@ -1,5 +1,5 @@ import { html, TemplateResult } from "lit"; -import { DataFactory, Literal, NamedNode, Quad, Store, Term, Util } from "n3"; +import { DataFactory, Literal, NamedNode, Quad, Store, Term } from "n3"; import { NodeDisplay } from "./NodeDisplay"; import { SuffixLabels } from "./suffixLabels"; import { @@ -8,7 +8,7 @@ predsForSubj, TypeToSubjs, } from "./tabulate"; -import { View } from "./view_loader"; +import { TableDesc, View } from "./view_loader"; const { namedNode } = DataFactory; @@ -30,12 +30,18 @@ this.graph = graph; const labels = new SuffixLabels(); - this._addLabelsForAllTerms(labels); + this._addLabelsForAllTerms(this.graph, labels); + + if (this.view.graph) { + this._addLabelsForAllTerms(this.view.graph, labels); + } this.nodeDisplay = new NodeDisplay(labels); } - _addLabelsForAllTerms(labels: SuffixLabels) { - return this.graph.forEach( + _addLabelsForAllTerms(graph: Store, labels: SuffixLabels) { + console.log("_addLabelsForAllTerms"); + + graph.forEach( (q: Quad) => { if (q.subject.termType === "NamedNode") { labels.planDisplayForNode(q.subject); @@ -144,11 +150,20 @@ }; } - _multiSubjsTypeBlock(byType: TypeToSubjs, typeUri: NamedNode) { - const layout = new MultiSubjsTypeBlockLayout(this.graph, byType, typeUri); + _multiSubjsTypeBlock(byType: TypeToSubjs, table: TableDesc) { + const layout = new MultiSubjsTypeBlockLayout(this.graph, byType, table); + + let typeNames = [html`${this.nodeDisplay.render(table.primary)}`]; + if (table.joins) { + typeNames.push(html` joined with [`); + for (let j of table.joins) { + typeNames.push(html`${this.nodeDisplay.render(j)}`); + } + typeNames.push(html`]`); + } return html` - <div>[icon] ${this.nodeDisplay.render(typeUri)} type resources</div> + <div>[icon] Resources of type ${typeNames}</div> <div class="typeBlockScroll"> <table class="typeBlock"> ${this._thead(layout)} ${layout.subjs.map(this._instanceRow(layout))} @@ -162,9 +177,10 @@ const { byType, typesPresent, untypedSubjs } = groupByRdfType(this.graph); let viewTitle = html` (no view)`; if (this.view.url) { - viewTitle = html` using view <a href="${this.view.url}">${this.view.label()}</a>`; + viewTitle = html` using view + <a href="${this.view.url}">${this.view.label()}</a>`; } - const typesToShow = this.view.typesToShow(typesPresent); + const tables = this.view.toplevelTables(typesPresent); return html` <section> <h2> @@ -175,9 +191,7 @@ These statements are all in the <span data-bind="html: $root.createCurie(graphUri())">...</span> graph.--> </div> - ${typesToShow.map((t: NamedNode) => - this._multiSubjsTypeBlock(byType, t) - )} + ${tables.map((t: TableDesc) => this._multiSubjsTypeBlock(byType, t))} <div class="spoGrid"> ${untypedSubjs.map(this._subjPredObjsBlock.bind(this))} </div>
--- a/src/suffixLabels.ts Thu Jan 13 21:32:18 2022 -0800 +++ b/src/suffixLabels.ts Fri Feb 11 20:27:02 2022 -0800 @@ -2,7 +2,8 @@ type SuffixesNode = { usedBy?: string; children: Map<string, SuffixesNode> }; type DisplayNode = { label?: string; link?: string }; -class SuffixLabels { + +export class SuffixLabels { displayNodes: Map<string, DisplayNode>; usedSuffixes: SuffixesNode; constructor() { @@ -63,7 +64,11 @@ // a substring to show for this uri getLabelForNode(node: string) { - return this.displayNodes.get(node)!.label; + const dn = this.displayNodes.get(node); + if (dn === undefined) { + throw new Error(`you never called planDisplayForNode on ${node}`); + } + return dn.label; } static _tailSegments(uri: string, n: number) { @@ -74,5 +79,3 @@ return uri.substr(i + 1); } } - -export { SuffixLabels };
--- a/src/tabulate.ts Thu Jan 13 21:32:18 2022 -0800 +++ b/src/tabulate.ts Fri Feb 11 20:27:02 2022 -0800 @@ -10,6 +10,7 @@ Term, Util, } from "n3"; +import { TableDesc } from "./view_loader"; const { namedNode } = DataFactory; @@ -110,8 +111,8 @@ subjs: NamedNode[]; preds: NamedNode[]; graphCells: Immutable.Map<ISP, Immutable.Set<Term>>; - constructor(graph: Store, byType: TypeToSubjs, typeUri: NamedNode) { - const subjSet = byType.get(typeUri); + constructor(graph: Store, byType: TypeToSubjs, table: TableDesc) { + const subjSet = byType.get(table.primary); this.subjs = subjSet ? Array.from(subjSet) : []; this.subjs.sort();
--- a/src/view_loader.ts Thu Jan 13 21:32:18 2022 -0800 +++ b/src/view_loader.ts Fri Feb 11 20:27:02 2022 -0800 @@ -12,6 +12,13 @@ throw new Error("no elems"); } +export interface TableDesc { + uri: NamedNode; + primary: NamedNode; + joins: NamedNode[]; +} + + export class View { graph: Store; ready: Promise<null>; @@ -42,11 +49,16 @@ } // filtered+ordered list of types to show at the top level - typesToShow(typesPresent: NamedNode[]): NamedNode[] { - const ret: NamedNode[] = []; + toplevelTables(typesPresent: NamedNode[]): TableDesc[] { + const ret: TableDesc[] = []; for (let table of this.graph.getObjects(this.viewRoot, EX("table"), null)) { - const tableType = uriValue(this.graph, table, EX("showsType")); - ret.push(tableType); + const tableType = uriValue(this.graph, table, EX("primaryType")); + const joins: NamedNode[] = []; + for (let joinType of this.graph.getObjects(table, EX("joinType"), null)) { + joins.push(joinType as NamedNode); + } + joins.sort(); + ret.push({ uri: table as NamedNode, primary: tableType, joins: joins }); } ret.sort(); return ret;