Mercurial > code > home > repos > streamed-graph
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 } |