comparison src/graph_view.js @ 3:a7ba8627a7b6

still trying to make imports work. add other files too
author drewp@bigasterisk.com
date Wed, 04 Dec 2019 00:09:15 -0800
parents
children
comparison
equal deleted inserted replaced
2:6cd3aaf431b6 3:a7ba8627a7b6
1 // from /my/site/homepage/www/rdf/browse/graphView.js
2
3
4 import { SuffixLabels } from './suffixLabels.js';
5
6 const groupByRdfType = (graph) => {
7 const env = graph.store.rdf;
8 const rdfType = env.createNamedNode('rdf:type');
9 const byType = new Map(); // type : subjs
10 const untyped = new Set(); // subjs
11 graph.quadStore.quads({}, (q) => {
12 let subjType = null;
13 graph.quadStore.quads({subject: q.subject,
14 predicate: rdfType},
15 (q2) => { subjType = q2.object; });
16 if (subjType){
17 subjType = subjType.toString();
18 if (!byType.has(subjType)) {
19 byType.set(subjType, new Set());
20 }
21 byType.get(subjType).add(q.subject.toString());
22 } else {
23 untyped.add(q.subject.toString());
24 }
25
26 });
27 return {byType: byType, untyped: untyped};
28 };
29
30 const graphView = (graph) => {
31 const env = graph.store.rdf;
32
33 const labels = new SuffixLabels();
34 graph.quadStore.quads({}, (q) => {
35 if (q.subject.interfaceName == "NamedNode") { labels.planDisplayForNode(q.subject); }
36 if (q.predicate.interfaceName == "NamedNode") { labels.planDisplayForNode(q.predicate); }
37 if (q.object.interfaceName == "NamedNode") { labels.planDisplayForNode(q.object); }
38 if (q.object.interfaceName == "Literal" && q.object.datatype) { labels.planDisplayForNode(env.createNamedNode(q.object.datatype)); }
39 });
40
41 const rdfNode = (n) => {
42 if (n.interfaceName == "Literal") {
43 let dtPart = "";
44 if (n.datatype) {
45 dtPart = html`
46 ^^<span class="literalType">
47 ${rdfNode(env.createNamedNode(n.datatype))}
48 </span>`;
49 }
50 return html`<span class="literal">${n.nominalValue}${dtPart}</span>`;
51 }
52 if (n.interfaceName == "NamedNode") {
53 let dn = labels.getLabelForNode(n);
54 if (dn.match(/XMLSchema#.*/)) { dn = dn.replace('XMLSchema#', 'xsd:'); }
55 if (dn.match(/rdf-schema#.*/)) { dn = dn.replace('rdf-schema#', 'rdfs:'); }
56 return html`<a class="graphUri" href="${n.toString()}">${dn}</a>`;
57 }
58
59 return html`[${n.interfaceName} ${n.toNT()}]`;
60 }
61
62 const objBlock = (obj) => {
63 return html`
64 <div class="object">
65 ${rdfNode(obj)} <!-- indicate what source or graph said this stmt -->
66 </div>
67 `;
68 };
69
70 /// bunch of table rows
71 const predBlock = (subj, pred) => {
72 const objsSet = new Set();
73 graph.quadStore.quads({ subject: subj, predicate: pred }, (q) => {
74
75 if (q.object.length) {
76 console.log(q.object)
77 }
78 objsSet.add(q.object);
79 });
80 const objs = Array.from(objsSet.values());
81 objs.sort();
82 return html`
83 <div class="predicate">${rdfNode(pred)}
84 <div>
85 ${objs.map(objBlock)}
86 </div>
87 </div>
88 `;
89 };
90
91 const {byType, untyped} = groupByRdfType(graph);
92 const typedSubjs = Array.from(byType.keys());
93 typedSubjs.sort();
94
95 const untypedSubjs = Array.from(untyped.values());
96 untypedSubjs.sort();
97
98 const subjBlock = (subj) => {
99 const subjNode = env.createNamedNode(subj);
100 const predsSet = new Set();
101 graph.quadStore.quads({ subject: subjNode }, (q) => {
102 predsSet.add(q.predicate);
103 });
104 const preds = Array.from(predsSet.values());
105 preds.sort();
106 return html`
107 <div class="subject">${rdfNode(subjNode)}
108 <!-- todo: special section for uri/type-and-icon/label/comment -->
109 <div>
110 ${preds.map((p) => { return predBlock(subjNode, p); })}
111 </div>
112 </div>
113 `;
114 };
115 const byTypeBlock = (typeUri) => {
116 const subjs = Array.from(byType.get(typeUri));
117 subjs.sort();
118
119 const graphCells = new Map(); // [subj, pred] : objs
120 const preds = new Set();
121
122 subjs.forEach((subj) => {
123 graph.quadStore.quads({subject: env.createNamedNode(subj)}, (q) => {
124 preds.add(q.predicate.toString());
125 const cellKey = subj + '|||' + q.predicate.toString();
126 if (!graphCells.has(cellKey)) {
127 graphCells.set(cellKey, new Set());
128 }
129 graphCells.get(cellKey).add(q.object);
130 });
131 });
132 const predsList = Array.from(preds);
133 predsList.splice(predsList.indexOf('http://www.w3.org/1999/02/22-rdf-syntax-ns#type'), 1);
134 // also pull out label, which should be used on 1st column
135 predsList.sort();
136
137 const thead = () => {
138 const predColumnHead = (pred) => {
139 return html`<th>${rdfNode(env.createNamedNode(pred))}</th>`;
140 };
141 return html`
142 <thead>
143 <tr>
144 <th></th>
145 ${predsList.map(predColumnHead)}
146 </tr>
147 </thead>`;
148 };
149
150 const instanceRow = (subj) => {
151 const cell = (pred) => {
152 const objs = graphCells.get(subj + '|||' + pred);
153 if (!objs) {
154 return html`<td></td>`;
155 }
156 const objsList = Array.from(objs);
157 objsList.sort();
158 const draw = (obj) => {
159 return html`<div>${rdfNode(obj)}</div>`
160 };
161 return html`<td>${objsList.map(draw)}</td>`;
162 };
163
164 return html`
165 <tr>
166 <td>${rdfNode(env.createNamedNode(subj))}</td>
167 ${predsList.map(cell)}
168 </tr>
169 `;
170 };
171
172 return html`
173 <div>[icon] ${rdfNode(env.createNamedNode(typeUri))} resources</div>
174 <div class="typeBlockScroll">
175 <table class="typeBlock">
176 ${thead()}
177 ${subjs.map(instanceRow)}
178 </table>
179 </div>
180 `;
181 };
182
183 return html`
184 <link rel="stylesheet" href="/rdf/browse/style.css">
185
186 <section>
187 <h2>
188 Current graph (<a href="${graph.events.url}">${graph.events.url}</a>)
189 </h2>
190 <div>
191 <!-- todo: graphs and provenance.
192 These statements are all in the
193 <span data-bind="html: $root.createCurie(graphUri())">...</span> graph.-->
194 </div>
195 ${typedSubjs.map(byTypeBlock)}
196 <div class="spoGrid">
197 ${untypedSubjs.map(subjBlock)}
198 </div>
199 </section>
200 `;
201 }
202 export { graphView }