# HG changeset patch # User drewp@bigasterisk.com # Date 1644640022 28800 # Node ID 26c55d5d520293b16a72c6870251e1f397138f12 # Parent 4d19759d0d9ae65d06711b72e81e25defd948f6c WIP on views & joins diff -r 4d19759d0d9a -r 26c55d5d5202 demo/public/repos.n3 --- 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 . diff -r 4d19759d0d9a -r 26c55d5d5202 src/graph_view.ts --- 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` -
[icon] ${this.nodeDisplay.render(typeUri)} type resources
+
[icon] Resources of type ${typeNames}
${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 ${this.view.label()}`; + viewTitle = html` using view + ${this.view.label()}`; } - const typesToShow = this.view.typesToShow(typesPresent); + const tables = this.view.toplevelTables(typesPresent); return html`

@@ -175,9 +191,7 @@ These statements are all in the ... graph.--> - ${typesToShow.map((t: NamedNode) => - this._multiSubjsTypeBlock(byType, t) - )} + ${tables.map((t: TableDesc) => this._multiSubjsTypeBlock(byType, t))}
${untypedSubjs.map(this._subjPredObjsBlock.bind(this))}
diff -r 4d19759d0d9a -r 26c55d5d5202 src/suffixLabels.ts --- 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 }; type DisplayNode = { label?: string; link?: string }; -class SuffixLabels { + +export class SuffixLabels { displayNodes: Map; 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 }; diff -r 4d19759d0d9a -r 26c55d5d5202 src/tabulate.ts --- 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>; - 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(); diff -r 4d19759d0d9a -r 26c55d5d5202 src/view_loader.ts --- 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; @@ -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;