Mercurial > code > home > repos > streamed-graph
changeset 49:c16a331f42e5
rewrap; stylesheet
author | drewp@bigasterisk.com |
---|---|
date | Thu, 09 Jan 2020 00:05:32 -0800 |
parents | b8e5850acca0 |
children | 1264ba9ffb10 |
files | src/graph_view.ts |
diffstat | 1 files changed, 190 insertions(+), 130 deletions(-) [+] |
line wrap: on
line diff
--- a/src/graph_view.ts Thu Jan 09 00:04:45 2020 -0800 +++ b/src/graph_view.ts Thu Jan 09 00:05:32 2020 -0800 @@ -1,69 +1,88 @@ -import { html, TemplateResult } from 'lit-html'; -import { Quad, Term, N3Store } from 'n3'; -import { DataFactory, Util } from 'n3'; +import { html, TemplateResult } from "lit-html"; +import { Quad, Term, N3Store } from "n3"; +import { DataFactory, Util } from "n3"; const { namedNode } = DataFactory; import * as RDF from "rdf-js"; type NamedNode = RDF.NamedNode; -import { SuffixLabels } from './suffixLabels'; +import { SuffixLabels } from "./suffixLabels"; // import ns from 'n3/src/IRIs'; // const { rdf } = ns; -const rdf = { type: namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type")}; +const rdf = { + type: namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type") +}; type TypeToSubjs = Map<NamedNode, Set<NamedNode>>; -function groupByRdfType(graph: N3Store): { byType: TypeToSubjs, untyped: Set<NamedNode> } { +function groupByRdfType( + graph: N3Store +): { byType: TypeToSubjs; untyped: Set<NamedNode> } { const rdfType = rdf.type; const byType: TypeToSubjs = new Map(); const untyped: Set<NamedNode> = new Set(); // subjs const internSubjs = new Map<string, NamedNode>(); - graph.forEach((q) => { - if (!Util.isNamedNode(q.subject)) { - throw new Error("unsupported " + q.subject.value); - } - const subj = q.subject as NamedNode; + graph.forEach( + q => { + if (!Util.isNamedNode(q.subject)) { + throw new Error("unsupported " + q.subject.value); + } + const subj = q.subject as NamedNode; + + let subjType: NamedNode | null = null; - let subjType: NamedNode | null = null; - - graph.forObjects((o: Quad) => { - if (Util.isNamedNode(o.object)) { - subjType = o.object as NamedNode; - } - }, subj, rdfType, null); + graph.forObjects( + (o: Quad) => { + if (Util.isNamedNode(o.object)) { + subjType = o.object as NamedNode; + } + }, + subj, + rdfType, + null + ); - if (subjType !== null) { - // (subj, rdf:type, subjType) in graph - if (!byType.has(subjType)) { - byType.set(subjType, new Set()); + if (subjType !== null) { + // (subj, rdf:type, subjType) in graph + if (!byType.has(subjType)) { + byType.set(subjType, new Set()); + } + (byType.get(subjType) as Set<NamedNode>).add(subj); + } else { + // no rdf:type stmt in graph + if (!internSubjs.has(subj.value)) { + internSubjs.set(subj.value, subj); + } + const intSubj: NamedNode = internSubjs.get( + subj.value as string + ) as NamedNode; + untyped.add(intSubj); } - (byType.get(subjType) as Set<NamedNode>).add(subj); - } else { - // no rdf:type stmt in graph - if (!internSubjs.has(subj.value)) { - internSubjs.set(subj.value, subj); - } - const intSubj: NamedNode = internSubjs.get(subj.value as string) as NamedNode; - untyped.add(intSubj); - } - }, null, null, null, null); + }, + null, + null, + null, + null + ); return { byType: byType, untyped: untyped }; } - class NodeDisplay { labels: SuffixLabels; constructor(labels: SuffixLabels) { this.labels = labels; } - getHtml(n: Term|NamedNode): TemplateResult { + getHtml(n: Term | NamedNode): TemplateResult { if (n.termType == "Literal") { let dtPart: any = ""; if (n.datatype) { dtPart = html` - ^^<span class="literalType"> - ${this.getHtml(n.datatype)} - </span>`; + ^^<span class="literalType"> + ${this.getHtml(n.datatype)} + </span> + `; } - return html`<span class="literal">${n.value}${dtPart}</span>`; + return html` + <span class="literal">${n.value}${dtPart}</span> + `; } if (n.termType == "NamedNode") { @@ -73,7 +92,8 @@ ["http://www.w3.org/1999/02/22-rdf-syntax-ns#", "rdf:"], ["http://www.w3.org/2000/01/rdf-schema#", "rdfs:"], ["http://purl.org/dc/elements/1.1/", "dc:"], - ["http://www.w3.org/2001/XMLSchema#", "xsd:"]]) { + ["http://www.w3.org/2001/XMLSchema#", "xsd:"] + ]) { if (uriValue?.startsWith(long)) { uriValue = short + uriValue.substr(long.length); shortened = true; @@ -81,7 +101,6 @@ } } if (!shortened) { - let dn: string | undefined = this.labels.getLabelForNode(uriValue); if (dn === undefined) { throw new Error(`dn=${dn}`); @@ -89,11 +108,14 @@ uriValue = dn; } - - return html`<a class="graphUri" href="${n.value}">${uriValue}</a>`; + return html` + <a class="graphUri" href="${n.value}">${uriValue}</a> + `; } - return html`[${n.termType} ${n.value}]`; + return html` + [${n.termType} ${n.value}] + `; } } @@ -111,28 +133,49 @@ } _addLabelsForAllTerms(labels: SuffixLabels) { - return this.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); + return this.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 + ); } _subjBlock(subj: NamedNode) { const predsSet: Set<NamedNode> = new Set(); - this.graph.forEach((q: Quad) => { - predsSet.add(q.predicate as NamedNode); - }, subj, null, null, null); + this.graph.forEach( + (q: Quad) => { + predsSet.add(q.predicate as NamedNode); + }, + subj, + null, + null, + null + ); const preds = Array.from(predsSet.values()); preds.sort(); return html` - <div class="subject">${this.nodeDisplay.getHtml(subj)} + <div class="subject"> + ${this.nodeDisplay.getHtml(subj)} <!-- todo: special section for uri/type-and-icon/label/comment --> <div> - ${preds.map((p) => { return this._predBlock(subj, p); })} + ${preds.map(p => { + return this._predBlock(subj, p); + })} </div> </div> `; @@ -141,20 +184,28 @@ _objBlock(obj: Term) { return html` <div class="object"> - ${this.nodeDisplay.getHtml(obj)} <!-- indicate what source or graph said this stmt --> + ${this.nodeDisplay.getHtml(obj)} + <!-- indicate what source or graph said this stmt --> </div> `; } _predBlock(subj: NamedNode, pred: NamedNode) { const objsSet = new Set<Term>(); - this.graph.forEach((q: Quad) => { - objsSet.add(q.object); - }, subj, pred, null, null); + this.graph.forEach( + (q: Quad) => { + objsSet.add(q.object); + }, + subj, + pred, + null, + null + ); const objs = Array.from(objsSet.values()); objs.sort(); return html` - <div class="predicate">${this.nodeDisplay.getHtml(pred)} + <div class="predicate"> + ${this.nodeDisplay.getHtml(pred)} <div> ${objs.map(this._objBlock.bind(this))} </div> @@ -162,18 +213,19 @@ `; } - byTypeBlock(byType: TypeToSubjs, typeUri: NamedNode) { const subjSet = byType.get(typeUri); - const subjs: Array<NamedNode> = subjSet ? Array.from(subjSet) : []; - subjs.sort(); + const subjs: Array<NamedNode> = subjSet ? Array.from(subjSet) : []; + subjs.sort(); - const graphCells = new Map<string, Set<Term>>(); // [subj, pred] : objs - const makeCellKey = (subj: NamedNode, pred: NamedNode) => subj.value + '|||' + pred.value; - const preds = new Set<NamedNode>(); + const graphCells = new Map<string, Set<Term>>(); // [subj, pred] : objs + const makeCellKey = (subj: NamedNode, pred: NamedNode) => + subj.value + "|||" + pred.value; + const preds = new Set<NamedNode>(); - subjs.forEach((subj: NamedNode) => { - this.graph.forEach((q: Quad) => { + subjs.forEach((subj: NamedNode) => { + this.graph.forEach( + (q: Quad) => { if (!Util.isNamedNode(q.predicate)) { throw new Error(); } @@ -183,61 +235,73 @@ graphCells.set(cellKey, new Set<Term>()); } graphCells.get(cellKey)!.add(q.object); - }, subj, null, null, null); - }); - const predsList = Array.from(preds); - predsList.splice(predsList.indexOf(rdf.type), 1); - // also pull out label, which should be used on 1st column - predsList.sort(); + }, + subj, + null, + null, + null + ); + }); + const predsList = Array.from(preds); + predsList.splice(predsList.indexOf(rdf.type), 1); + // also pull out label, which should be used on 1st column + predsList.sort(); - const thead = () => { - const predColumnHead = (pred: NamedNode) => { - return html`<th>${this.nodeDisplay.getHtml(pred)}</th>`; + const thead = () => { + const predColumnHead = (pred: NamedNode) => { + return html` + <th>${this.nodeDisplay.getHtml(pred)}</th> + `; + }; + return html` + <thead> + <tr> + <th></th> + ${predsList.map(predColumnHead)} + </tr> + </thead> + `; + }; + + const instanceRow = (subj: NamedNode) => { + const cell = (pred: NamedNode) => { + const objs = graphCells.get(subj + "|||" + pred); + if (!objs) { + return html` + <td></td> + `; + } + const objsList = Array.from(objs); + objsList.sort(); + const draw = (obj: Term) => { + return html` + <div>${this.nodeDisplay.getHtml(obj)}</div> + `; }; return html` - <thead> - <tr> - <th></th> - ${predsList.map(predColumnHead)} - </tr> - </thead>`; - }; - - const instanceRow = (subj: NamedNode) => { - const cell = (pred: NamedNode) => { - const objs = graphCells.get(subj + '|||' + pred); - if (!objs) { - return html`<td></td>`; - } - const objsList = Array.from(objs); - objsList.sort(); - const draw = (obj: Term) => { - return html`<div>${this.nodeDisplay.getHtml(obj)}</div>` - }; - return html`<td>${objsList.map(draw)}</td>`; - }; - - return html` - <tr> - <td>${this.nodeDisplay.getHtml(subj)}</td> - ${predsList.map(cell)} - </tr> - `; + <td>${objsList.map(draw)}</td> + `; }; return html` - <div>[icon] ${this.nodeDisplay.getHtml(typeUri)} resources</div> - <div class="typeBlockScroll"> - <table class="typeBlock"> - ${thead()} - ${subjs.map(instanceRow)} - </table> - </div> - `; + <tr> + <td>${this.nodeDisplay.getHtml(subj)}</td> + ${predsList.map(cell)} + </tr> + `; }; + return html` + <div>[icon] ${this.nodeDisplay.getHtml(typeUri)} resources</div> + <div class="typeBlockScroll"> + <table class="typeBlock"> + ${thead()} ${subjs.map(instanceRow)} + </table> + </div> + `; + } + makeTemplate(): TemplateResult { - const { byType, untyped } = groupByRdfType(this.graph); const typedSubjs = Array.from(byType.keys()); typedSubjs.sort(); @@ -246,22 +310,18 @@ untypedSubjs.sort(); return html` - <link rel="stylesheet" href="../src/streamed-graph.css"> - - <section> - <h2> - Current graph (<a href="${this.url}">${this.url}</a>) - </h2> - <div> - <!-- todo: graphs and provenance. + <section> + <h2>Current graph (<a href="${this.url}">${this.url}</a>)</h2> + <div> + <!-- todo: graphs and provenance. These statements are all in the <span data-bind="html: $root.createCurie(graphUri())">...</span> graph.--> - </div> - ${typedSubjs.map((t: NamedNode) => this.byTypeBlock(byType, t))} - <div class="spoGrid"> - ${untypedSubjs.map(this._subjBlock.bind(this))} - </div> - </section> - `; + </div> + ${typedSubjs.map((t: NamedNode) => this.byTypeBlock(byType, t))} + <div class="spoGrid"> + ${untypedSubjs.map(this._subjBlock.bind(this))} + </div> + </section> + `; } }