Mercurial > code > home > repos > streamed-graph
diff src/graph_view.ts @ 15:7ca4ff2088c3
managed to use a newer ts or something, so this includes a bunch of type fixes too
author | drewp@bigasterisk.com |
---|---|
date | Sun, 08 Dec 2019 23:32:12 -0800 |
parents | 26d3e4860adc |
children | 9ec3cbc8791a |
line wrap: on
line diff
--- a/src/graph_view.ts Fri Dec 06 20:34:01 2019 -0800 +++ b/src/graph_view.ts Sun Dec 08 23:32:12 2019 -0800 @@ -1,208 +1,238 @@ // from /my/site/homepage/www/rdf/browse/graphView.js -/// <reference types="./n3.d.ts"> +//reference types="./n3.d.ts"> -import { html } from 'lit-html'; +import { html, TemplateResult } from 'lit-html'; import { SuffixLabels } from './suffixLabels'; -import { NamedNode, N3Store } from 'n3'; - -import ns from 'n3/src/IRIs'; -const {rdf} = ns; +import { Quad, Term, NamedNode, N3Store } from '../node_modules/@types/n3/index'; +import { DataFactory, Util } from 'n3'; +const { namedNode } = DataFactory; +// import ns from 'n3/src/IRIs'; +// const { rdf } = ns; -const groupByRdfType = (graph: N3Store) => { - const rdfType = new NamedNode(rdf.type); - const byType: Map<NamedNode, Set<NamedNode>> = new Map(); // type : subjs - const untyped = new Set(); // subjs - graph.getQuads({}, (q) => { - let subjType = null; - graph.getQuads({ - subject: q.subject, - predicate: rdfType - }, - (q2) => { subjType = q2.object; }); - if (subjType) { - subjType = subjType.toString(); +type TypeToSubjs = Map<NamedNode, Set<NamedNode>>; +function groupByRdfType(graph: N3Store): { byType: TypeToSubjs, untyped: Set<NamedNode> } { + const rdfType = namedNode('rdf:type'); + const byType: TypeToSubjs = new Map(); // type : subjs + const untyped: Set<NamedNode> = new Set(); // subjs + graph.forEach((q) => { + let subjType: NamedNode | null = null; + + graph.forObjects((o: Quad) => { + if (Util.isNamedNode(o.object)) { + subjType = o.object as NamedNode; + } + }, q.subject, rdfType, null); + + if (subjType !== null) { if (!byType.has(subjType)) { byType.set(subjType, new Set()); } - byType.get(subjType).add(q.subject.toString()); + (byType.get(subjType) as Set<NamedNode>).add(q.subject as NamedNode); } else { - untyped.add(q.subject.toString()); + untyped.add(q.subject as NamedNode); } - - }); + }, null, null, null, null); return { byType: byType, untyped: untyped }; -}; +} -const graphView = (graph: N3Store) => { - const labels = new SuffixLabels(); - graph.getQuads({}, (q) => { - if (q.subject.interfaceName == "NamedNode") { labels.planDisplayForNode(q.subject); } - if (q.predicate.interfaceName == "NamedNode") { labels.planDisplayForNode(q.predicate); } - if (q.object.interfaceName == "NamedNode") { labels.planDisplayForNode(q.object); } - if (q.object.interfaceName == "Literal" && q.object.datatype) { labels.planDisplayForNode(new NamedNode(q.object.datatype)); } - }); - const rdfNode = (n) => { - if (n.interfaceName == "Literal") { +class NodeDisplay { + labels: SuffixLabels; + constructor(labels: SuffixLabels) { + this.labels = labels; + } + getHtml(n: Term): TemplateResult { + if (n.termType == "Literal") { let dtPart: any = ""; if (n.datatype) { dtPart = html` - ^^<span class="literalType"> - ${rdfNode(new NamedNode(n.datatype))} - </span>`; + ^^<span class="literalType"> + ${this.getHtml(n.datatype)} + </span>`; } - return html`<span class="literal">${n.nominalValue}${dtPart}</span>`; - } - if (n.interfaceName == "NamedNode") { - let dn = labels.getLabelForNode(n); - if (dn.match(/XMLSchema#.*/)) { dn = dn.replace('XMLSchema#', 'xsd:'); } - if (dn.match(/rdf-schema#.*/)) { dn = dn.replace('rdf-schema#', 'rdfs:'); } - return html`<a class="graphUri" href="${n.toString()}">${dn}</a>`; + return html`<span class="literal">${n.value}${dtPart}</span>`; } - return html`[${n.interfaceName} ${n.toNT()}]`; + if (n.termType == "NamedNode") { + let dn: string | undefined = this.labels.getLabelForNode(n.value); + if (dn === undefined) { + throw new Error(`dn=${dn}`); + } + if (dn!.match(/XMLSchema#.*/)) { + dn = dn!.replace('XMLSchema#', 'xsd:'); + } + if (dn!.match(/rdf-schema#.*/)) { + dn = dn!.replace('rdf-schema#', 'rdfs:'); + } + return html`<a class="graphUri" href="${n.value}">${dn}</a>`; + } + + return html`[${n.termType} ${n.value}]`; + } +} + +export class GraphView { + url: string; + graph: N3Store; + nodeDisplay: NodeDisplay; + constructor(url: string, graph: N3Store) { + this.url = url; + this.graph = graph; + + const labels = new SuffixLabels(); + this._addLabelsForAllTerms(labels); + this.nodeDisplay = new NodeDisplay(labels); } - const objBlock = (obj) => { - return html` - <div class="object"> - ${rdfNode(obj)} <!-- indicate what source or graph said this stmt --> - </div> - `; - }; + _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); + } - /// bunch of table rows - const predBlock = (subj, pred) => { - const objsSet = new Set(); - graph.getQuads({ subject: subj, predicate: pred }, (q) => { - - if (q.object.length) { - console.log(q.object) - } - objsSet.add(q.object); - }); - const objs = Array.from(objsSet.values()); - objs.sort(); + _subjBlock(subj: NamedNode) { + const predsSet: Set<NamedNode> = new Set(); + 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="predicate">${rdfNode(pred)} + <div class="subject">${this.nodeDisplay.getHtml(subj)} + <!-- todo: special section for uri/type-and-icon/label/comment --> <div> - ${objs.map(objBlock)} + ${preds.map((p) => { return this._predBlock(subj, p); })} </div> </div> `; - }; + } - const { byType, untyped } = groupByRdfType(graph); - const typedSubjs = Array.from(byType.keys()); - typedSubjs.sort(); - - const untypedSubjs = Array.from(untyped.values()); - untypedSubjs.sort(); + _objBlock(obj: Term) { + return html` + <div class="object"> + ${this.nodeDisplay.getHtml(obj)} <!-- indicate what source or graph said this stmt --> + </div> + `; + } - const subjBlock = (subj) => { - const subjNode = new NamedNode(subj); - const predsSet = new Set(); - graph.getQuads({ subject: subjNode }, (q) => { - predsSet.add(q.predicate); - }); - const preds = Array.from(predsSet.values()); - preds.sort(); + _predBlock(subj: NamedNode, pred: NamedNode) { + const objsSet = new Set(); + 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="subject">${rdfNode(subjNode)} - <!-- todo: special section for uri/type-and-icon/label/comment --> + <div class="predicate">${this.nodeDisplay.getHtml(pred)} <div> - ${preds.map((p) => { return predBlock(subjNode, p); })} + ${objs.map(this._objBlock.bind(this))} </div> </div> `; - }; - const byTypeBlock = (typeUri) => { - const subjs = Array.from(byType.get(typeUri)); - subjs.sort(); + } + - const graphCells = new Map(); // [subj, pred] : objs - const preds = new Set(); + // const byTypeBlock = (typeUri) => { + // const subjs = Array.from(byType.get(typeUri)); + // subjs.sort(); + + // const graphCells = new Map(); // [subj, pred] : objs + // const preds = new Set(); - subjs.forEach((subj) => { - graph.getQuads({ subject: new NamedNode(subj) }, (q) => { - preds.add(q.predicate.toString()); - const cellKey = subj + '|||' + q.predicate.toString(); - if (!graphCells.has(cellKey)) { - graphCells.set(cellKey, new Set()); - } - graphCells.get(cellKey).add(q.object); - }); - }); - const predsList = Array.from(preds); - predsList.splice(predsList.indexOf('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), 1); - // also pull out label, which should be used on 1st column - predsList.sort(); + // subjs.forEach((subj) => { + // graph.getQuads({ subject: new NamedNode(subj) }, (q) => { + // preds.add(q.predicate.toString()); + // const cellKey = subj + '|||' + q.predicate.toString(); + // if (!graphCells.has(cellKey)) { + // graphCells.set(cellKey, new Set()); + // } + // graphCells.get(cellKey).add(q.object); + // }); + // }); + // const predsList = Array.from(preds); + // predsList.splice(predsList.indexOf('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), 1); + // // also pull out label, which should be used on 1st column + // predsList.sort(); + + // const thead = () => { + // const predColumnHead = (pred) => { + // return html`<th>${rdfNode(new NamedNode(pred))}</th>`; + // }; + // return html` + // <thead> + // <tr> + // <th></th> + // ${predsList.map(predColumnHead)} + // </tr> + // </thead>`; + // }; - const thead = () => { - const predColumnHead = (pred) => { - return html`<th>${rdfNode(new NamedNode(pred))}</th>`; - }; - return html` - <thead> - <tr> - <th></th> - ${predsList.map(predColumnHead)} - </tr> - </thead>`; - }; + // const instanceRow = (subj) => { + // const cell = (pred) => { + // const objs = graphCells.get(subj + '|||' + pred); + // if (!objs) { + // return html`<td></td>`; + // } + // const objsList = Array.from(objs); + // objsList.sort(); + // const draw = (obj) => { + // return html`<div>${rdfNode(obj)}</div>` + // }; + // return html`<td>${objsList.map(draw)}</td>`; + // }; - const instanceRow = (subj) => { - const cell = (pred) => { - const objs = graphCells.get(subj + '|||' + pred); - if (!objs) { - return html`<td></td>`; - } - const objsList = Array.from(objs); - objsList.sort(); - const draw = (obj) => { - return html`<div>${rdfNode(obj)}</div>` - }; - return html`<td>${objsList.map(draw)}</td>`; - }; + // return html` + // <tr> + // <td>${rdfNode(new NamedNode(subj))}</td> + // ${predsList.map(cell)} + // </tr> + // `; + // }; - return html` - <tr> - <td>${rdfNode(new NamedNode(subj))}</td> - ${predsList.map(cell)} - </tr> - `; - }; + // return html` + // <div>[icon] ${rdfNode(new NamedNode(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(); + + const untypedSubjs = Array.from(untyped.values()); + untypedSubjs.sort(); return html` - <div>[icon] ${rdfNode(new NamedNode(typeUri))} resources</div> -<div class="typeBlockScroll"> - <table class="typeBlock"> - ${thead()} - ${subjs.map(instanceRow)} - </table> -</div> - `; - }; - - return html` - <link rel="stylesheet" href="/rdf/browse/style.css"> + <link rel="stylesheet" href="../src/streamed-graph.css"> - <section> - <h2> - Current graph (<a href="${graph.events.url}">${graph.events.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(byTypeBlock)} - <div class="spoGrid"> - ${untypedSubjs.map(subjBlock)} - </div> - </section> - `; + <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(byTypeBlock)} + <div class="spoGrid"> + ${untypedSubjs.map(this._subjBlock.bind(this))} + </div> + </section> + `; + } } -export { graphView }