@igea/oac_frontend 1.0.59 → 1.0.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const DataModel = require('../models/DataModel');
|
|
4
|
+
|
|
5
|
+
module.exports = function(serviceName) {
|
|
6
|
+
|
|
7
|
+
router.get('/view', (req, res) => {
|
|
8
|
+
|
|
9
|
+
let data = new DataModel(req, {
|
|
10
|
+
root: serviceName,
|
|
11
|
+
title: 'RDF viewer',
|
|
12
|
+
iri: req.query.iri
|
|
13
|
+
});
|
|
14
|
+
res.render('rdf/view.twig', data.toJson());
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return router
|
|
18
|
+
}
|
package/src/index.js
CHANGED
|
@@ -91,6 +91,9 @@ getPort.default({
|
|
|
91
91
|
const investigationRouter = require('./controllers/investigation.js')(serviceName);
|
|
92
92
|
app.use(`/${serviceName}/investigation`, investigationRouter);
|
|
93
93
|
|
|
94
|
+
const rdfRouter = require('./controllers/rdf.js')(serviceName);
|
|
95
|
+
app.use(`/${serviceName}/rdf`, rdfRouter);
|
|
96
|
+
|
|
94
97
|
const captchaRouter = require('./controllers/captcha.js');
|
|
95
98
|
app.use(`/${serviceName}/captcha`, captchaRouter);
|
|
96
99
|
// ---------------------------------------------------------------------
|
|
Binary file
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
const { createApp, ref } = Vue;
|
|
2
|
+
|
|
3
|
+
const appId = 'rdf-viewer-app';
|
|
4
|
+
|
|
5
|
+
const classColors = {
|
|
6
|
+
'E55_Type': 'rgba(0,255,0,0.70)',
|
|
7
|
+
'E7_Activity': 'rgba(174, 93, 56, 0.5)',
|
|
8
|
+
'E42_Identifier': 'rgba(0,0,255,0.5)',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const splitName = function(name){
|
|
12
|
+
name = name.split("/").pop();
|
|
13
|
+
name = name.split(":").pop();
|
|
14
|
+
name = name.split("#").pop();
|
|
15
|
+
return name;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const LoadingStatus = {
|
|
19
|
+
TODO: "todo",
|
|
20
|
+
PROGRESS: "progress",
|
|
21
|
+
DONE: "done"
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
25
|
+
const el = document.getElementById(appId);
|
|
26
|
+
|
|
27
|
+
// Definisci il componente TreeNode
|
|
28
|
+
const TreeNode = {
|
|
29
|
+
template: `
|
|
30
|
+
<div class="tree-node"
|
|
31
|
+
:style="{ 'padding-left': depth * 0 + 'px' }"
|
|
32
|
+
>
|
|
33
|
+
<div class="node-label" @click="toggleExpand" :style="styleNode(node)">
|
|
34
|
+
<span v-if="(node.predicates && node.predicates.length > 0) || (node.children && node.children.length > 0)">
|
|
35
|
+
{{ expanded ? '▼' : '▶' }}
|
|
36
|
+
</span>
|
|
37
|
+
<i v-if="node.loadStatus == 'todo'"
|
|
38
|
+
class="fa-brands fa-searchengin"
|
|
39
|
+
style="cursor:pointer;"
|
|
40
|
+
@click="loadNode(node)"
|
|
41
|
+
></i>
|
|
42
|
+
<img v-else-if="node.loadStatus == 'progress'"
|
|
43
|
+
src="/frontend/images/loading_icon.gif"
|
|
44
|
+
style="width:32px; height:32px;"
|
|
45
|
+
>
|
|
46
|
+
<i v-else style="margin-left:10px;"></i>
|
|
47
|
+
{{ node.label + ' ' + classesLabelFor(node) }}
|
|
48
|
+
</div>
|
|
49
|
+
<div v-if="expanded">
|
|
50
|
+
<template v-if="node.predicates && node.predicates.length > 0">
|
|
51
|
+
<div v-for="(predicate, index) in node.predicates" :key="index"
|
|
52
|
+
style="margin-left:20px;">
|
|
53
|
+
<div>
|
|
54
|
+
{{ predicate.label }}
|
|
55
|
+
</div>
|
|
56
|
+
<tree-node v-for="(child, index) in predicate.children"
|
|
57
|
+
:key="index"
|
|
58
|
+
:node="child"
|
|
59
|
+
:depth="depth + 1"
|
|
60
|
+
></tree-node>
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
<template v-else>
|
|
64
|
+
<tree-node v-for="(child, index) in node.children"
|
|
65
|
+
:key="index"
|
|
66
|
+
:node="child"
|
|
67
|
+
:depth="depth + 1"
|
|
68
|
+
></tree-node>
|
|
69
|
+
</template>
|
|
70
|
+
</div>
|
|
71
|
+
</div>`,
|
|
72
|
+
props: {
|
|
73
|
+
node: {
|
|
74
|
+
type: Object,
|
|
75
|
+
required: true
|
|
76
|
+
},
|
|
77
|
+
depth: {
|
|
78
|
+
type: Number,
|
|
79
|
+
default: 0
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
data() {
|
|
83
|
+
return {
|
|
84
|
+
expanded: true
|
|
85
|
+
};
|
|
86
|
+
},
|
|
87
|
+
methods: {
|
|
88
|
+
loadNode(node){
|
|
89
|
+
//this.$emit('load-node', node);
|
|
90
|
+
let event = new Event('load-node');
|
|
91
|
+
event.node = node;
|
|
92
|
+
el.dispatchEvent(event);
|
|
93
|
+
},
|
|
94
|
+
styleNode(node) {
|
|
95
|
+
var color = '#bbccdd';
|
|
96
|
+
if (node.classes && node.classes.length > 0) {
|
|
97
|
+
for(var i=0; i<node.classes.length; i++){
|
|
98
|
+
var clazz = node.classes[i];
|
|
99
|
+
if(classColors.hasOwnProperty(clazz)){
|
|
100
|
+
color = classColors[clazz];
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
'background-color': `${color}`
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
classesLabelFor(node){
|
|
110
|
+
var label = "";
|
|
111
|
+
if(node.classes && node.classes.length > 0){
|
|
112
|
+
var int_label = "";
|
|
113
|
+
for(var i=0; i<node.classes.length; i++){
|
|
114
|
+
var part = splitName(node.classes[i]);
|
|
115
|
+
if(i>0) int_label += ",";
|
|
116
|
+
int_label += part;
|
|
117
|
+
}
|
|
118
|
+
if(int_label.trim()!=""){
|
|
119
|
+
label = "[" + int_label + "]";
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return label;
|
|
123
|
+
},
|
|
124
|
+
toggleExpand() {
|
|
125
|
+
if ((this.node.predicates && this.node.predicates.length > 0) ||
|
|
126
|
+
(this.node.children && this.node.children.length > 0)) {
|
|
127
|
+
this.expanded = !this.expanded;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
// Definisci il componente TreeView
|
|
134
|
+
const TreeView = {
|
|
135
|
+
template: `
|
|
136
|
+
<div class="tree-view">
|
|
137
|
+
<tree-node
|
|
138
|
+
v-for="(node, index) in treeData"
|
|
139
|
+
:key="index"
|
|
140
|
+
:node="node"
|
|
141
|
+
:depth="0"
|
|
142
|
+
></tree-node>
|
|
143
|
+
</div>
|
|
144
|
+
`,
|
|
145
|
+
props: {
|
|
146
|
+
treeData: {
|
|
147
|
+
type: Array,
|
|
148
|
+
required: true
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
components: {
|
|
152
|
+
TreeNode
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
// Crea l'applicazione Vue
|
|
157
|
+
const app = Vue.createApp({
|
|
158
|
+
data() {
|
|
159
|
+
return {
|
|
160
|
+
rootIri: el.dataset.root_iri,
|
|
161
|
+
treeData: []
|
|
162
|
+
};
|
|
163
|
+
},
|
|
164
|
+
mounted() {
|
|
165
|
+
this.loadRoot();
|
|
166
|
+
el.addEventListener("load-node", (function(event) {
|
|
167
|
+
this.loadNodeData(event.node);
|
|
168
|
+
}).bind(this));
|
|
169
|
+
},
|
|
170
|
+
methods:{
|
|
171
|
+
loadRoot(){
|
|
172
|
+
var _this = this;
|
|
173
|
+
var url = "/backend/fuseki/rdf/rootResource?iri=" + this.rootIri;
|
|
174
|
+
fetch(url)
|
|
175
|
+
.then(response => response.json())
|
|
176
|
+
.then(r => {
|
|
177
|
+
if(r.success){
|
|
178
|
+
var data = r.data;
|
|
179
|
+
var classes = data.classes.split(",");
|
|
180
|
+
for(var i=0; i<classes.length; i++){
|
|
181
|
+
classes[i] = splitName(classes[i]);
|
|
182
|
+
}
|
|
183
|
+
_this.treeData = [{
|
|
184
|
+
label: data.label.split("/").pop(),
|
|
185
|
+
iri: decodeURIComponent(_this.rootIri),
|
|
186
|
+
classes: classes,
|
|
187
|
+
loadStatus: LoadingStatus.TODO,
|
|
188
|
+
predicates:[]
|
|
189
|
+
}];
|
|
190
|
+
}else{
|
|
191
|
+
alert('Error:', r.message);
|
|
192
|
+
}
|
|
193
|
+
})
|
|
194
|
+
.catch(error => {
|
|
195
|
+
console.log(error);
|
|
196
|
+
//alert('Errore durante il caricamento dei dati radice:', error);
|
|
197
|
+
});
|
|
198
|
+
},
|
|
199
|
+
loadNodeData(node){
|
|
200
|
+
var _this = this;
|
|
201
|
+
node.predicates=[];
|
|
202
|
+
var url = "/backend/fuseki/rdf/resourceOf?iri=" + encodeURIComponent(node.iri);
|
|
203
|
+
console.log(url)
|
|
204
|
+
node.loadStatus = LoadingStatus.PROGRESS;
|
|
205
|
+
fetch(url).then(response => response.json()).then(r => {
|
|
206
|
+
if(r.success){
|
|
207
|
+
var data = r.data;
|
|
208
|
+
var prev_predicate = null;
|
|
209
|
+
var index_predicate = -1;
|
|
210
|
+
for(var i=0; data.length; i++){
|
|
211
|
+
var predicate = splitName(data[i].predicate);
|
|
212
|
+
if(predicate != prev_predicate){
|
|
213
|
+
node.predicates.push({
|
|
214
|
+
label: predicate,
|
|
215
|
+
children: []
|
|
216
|
+
});
|
|
217
|
+
prev_predicate = predicate;
|
|
218
|
+
index_predicate++;
|
|
219
|
+
}
|
|
220
|
+
var classes = data[i].object.classes.split(",");
|
|
221
|
+
for(var j=0; j<classes.length; j++){
|
|
222
|
+
classes[j] = splitName(classes[j]);
|
|
223
|
+
}
|
|
224
|
+
node.predicates[index_predicate].children.push({
|
|
225
|
+
label: splitName(data[i].object.label),
|
|
226
|
+
iri: "<" + data[i].object.iri + ">",
|
|
227
|
+
classes: classes,
|
|
228
|
+
loadStatus: LoadingStatus.TODO
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}else{
|
|
232
|
+
alert('Error:', r.message);
|
|
233
|
+
}
|
|
234
|
+
node.loadStatus = LoadingStatus.DONE;
|
|
235
|
+
}).catch(error => {
|
|
236
|
+
node.loadStatus = LoadingStatus.DONE;
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// Registra il componente TreeView globalmente
|
|
243
|
+
app.component('tree-view', TreeView);
|
|
244
|
+
app.component('tree-node', TreeNode);
|
|
245
|
+
|
|
246
|
+
// Monta l'applicazione
|
|
247
|
+
app.mount(`#${appId}`);
|
|
248
|
+
|
|
249
|
+
});
|
|
@@ -33,8 +33,8 @@ const yasr = new Yasr(document.getElementById("yasr"), {
|
|
|
33
33
|
});
|
|
34
34
|
|
|
35
35
|
yasr.plugins["TableX"].config.uriHrefAdapter = function(uri) {
|
|
36
|
-
if(uri.startsWith("http://diagnostica/")) {
|
|
37
|
-
return "/frontend/
|
|
36
|
+
if(uri.startsWith("http://diagnostica/") || uri.startsWith("http://indagine/")) {
|
|
37
|
+
return "/frontend/rdf/view?iri=" + encodeURIComponent("<" + uri + ">");
|
|
38
38
|
} else {
|
|
39
39
|
return uri;
|
|
40
40
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{% set showSidebar = false %}
|
|
2
|
+
{% extends "../base.twig" %}
|
|
3
|
+
|
|
4
|
+
{% block extendHead %}
|
|
5
|
+
|
|
6
|
+
<!-- Font Awesome -->
|
|
7
|
+
<link rel="stylesheet" href="/{{ root }}/css/fa/css/all.min.css" />
|
|
8
|
+
|
|
9
|
+
<style>
|
|
10
|
+
.tree-node {
|
|
11
|
+
margin: 4px 0px;
|
|
12
|
+
margin-left: 20px;
|
|
13
|
+
border: solid 1px gray;
|
|
14
|
+
}
|
|
15
|
+
.node-label {
|
|
16
|
+
cursor: pointer;
|
|
17
|
+
}
|
|
18
|
+
.node-label:hover {
|
|
19
|
+
font-weight: bold;
|
|
20
|
+
}
|
|
21
|
+
</style>
|
|
22
|
+
|
|
23
|
+
{% endblock %}
|
|
24
|
+
|
|
25
|
+
{% block content %}
|
|
26
|
+
|
|
27
|
+
<div id="rdf-viewer-app"
|
|
28
|
+
data-root_iri="{{ iri }}"
|
|
29
|
+
style="margin-top:1rem!important; margin-bottom:1rem!important;">
|
|
30
|
+
<tree-view :tree-data="treeData"></tree-view>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<script src="/{{ root }}/js/app/vue-rdf.js"></script>
|
|
34
|
+
|
|
35
|
+
{% endblock %}
|