Mercurial > code > home > repos > streamed-graph
view src/graph_view.ts @ 9:26d3e4860adc
working on porting graph_view to n3.js. also working on making tests run
author | drewp@bigasterisk.com |
---|---|
date | Fri, 06 Dec 2019 09:19:43 -0800 |
parents | 6fefd287aff9 |
children | 7ca4ff2088c3 |
line wrap: on
line source
// from /my/site/homepage/www/rdf/browse/graphView.js /// <reference types="./n3.d.ts"> import { html } from 'lit-html'; import { SuffixLabels } from './suffixLabels'; import { NamedNode, N3Store } from 'n3'; 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(); if (!byType.has(subjType)) { byType.set(subjType, new Set()); } byType.get(subjType).add(q.subject.toString()); } else { untyped.add(q.subject.toString()); } }); 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") { let dtPart: any = ""; if (n.datatype) { dtPart = html` ^^<span class="literalType"> ${rdfNode(new NamedNode(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`[${n.interfaceName} ${n.toNT()}]`; } const objBlock = (obj) => { return html` <div class="object"> ${rdfNode(obj)} <!-- indicate what source or graph said this stmt --> </div> `; }; /// 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(); return html` <div class="predicate">${rdfNode(pred)} <div> ${objs.map(objBlock)} </div> </div> `; }; const { byType, untyped } = groupByRdfType(graph); const typedSubjs = Array.from(byType.keys()); typedSubjs.sort(); const untypedSubjs = Array.from(untyped.values()); untypedSubjs.sort(); 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(); return html` <div class="subject">${rdfNode(subjNode)} <!-- todo: special section for uri/type-and-icon/label/comment --> <div> ${preds.map((p) => { return predBlock(subjNode, p); })} </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(); 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 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` <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"> <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> `; } export { graphView }