@igea/oac_frontend 1.0.105 → 1.0.107
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 +1 -1
- package/src/controllers/investigation.js +1 -1
- package/src/public/js/app/vue-investigation.js +81 -0
- package/src/public/js/lib/sparnatural-main.js +1 -1
- package/src/views/v2/investigation/form_content.twig +2 -2
- package/src/views/v2/investigation/view.twig +234 -38
- package/src/views/v2/layout.twig +1 -0
package/package.json
CHANGED
|
@@ -389,6 +389,87 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
389
389
|
var intervalId = setInterval(() => {
|
|
390
390
|
if(_this.form.shadowRoot){
|
|
391
391
|
clearInterval(intervalId);
|
|
392
|
+
// 🔥 Fix alignment for add-property blocks
|
|
393
|
+
const shadow = _this.form.shadowRoot;
|
|
394
|
+
|
|
395
|
+
if (!shadow.querySelector('#oac-final-layout')) {
|
|
396
|
+
const style = document.createElement('style');
|
|
397
|
+
style.id = 'oac-final-layout';
|
|
398
|
+
style.textContent = `
|
|
399
|
+
|
|
400
|
+
/* ============================= */
|
|
401
|
+
/* Layout moderno a 3 elementi */
|
|
402
|
+
/* ============================= */
|
|
403
|
+
|
|
404
|
+
.property-instance {
|
|
405
|
+
display: flex !important;
|
|
406
|
+
align-items: center !important;
|
|
407
|
+
gap: 10px !important;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/* Label senza width fissa */
|
|
411
|
+
.property-instance label {
|
|
412
|
+
width: auto !important;
|
|
413
|
+
min-width: 220px !important;
|
|
414
|
+
white-space: nowrap !important;
|
|
415
|
+
flex-shrink: 0 !important;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/* Editor cresce */
|
|
419
|
+
.property-instance .editor {
|
|
420
|
+
flex: 1 1 auto !important;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/* 🔥 SPUNTA NON PIÙ ASSOLUTA */
|
|
424
|
+
.property-instance.valid::before {
|
|
425
|
+
position: static !important;
|
|
426
|
+
margin-right: 6px !important;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
`;
|
|
430
|
+
shadow.appendChild(style);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (!shadow.querySelector('#oac-fix-add-buttons')) {
|
|
434
|
+
const style = document.createElement('style');
|
|
435
|
+
style.id = 'oac-fix-add-buttons';
|
|
436
|
+
style.textContent = `
|
|
437
|
+
|
|
438
|
+
/* Sposta i blocchi add a sinistra */
|
|
439
|
+
shacl-property:not(:has(>.collapsible)),
|
|
440
|
+
shacl-property > .collapsible::part(content) {
|
|
441
|
+
align-items: flex-start !important;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/* Assicura che il + sia inline */
|
|
445
|
+
shacl-property .add-button {
|
|
446
|
+
align-self: flex-start !important;
|
|
447
|
+
margin-right: 0 !important;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
`;
|
|
451
|
+
shadow.appendChild(style);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
|
|
455
|
+
if (!shadow.querySelector('#oac-limit-editor-width')) {
|
|
456
|
+
const style = document.createElement('style');
|
|
457
|
+
style.id = 'oac-limit-editor-width';
|
|
458
|
+
style.textContent = `
|
|
459
|
+
|
|
460
|
+
.property-instance .editor {
|
|
461
|
+
flex-grow: 0 !important;
|
|
462
|
+
max-width: 500px !important;
|
|
463
|
+
width: 100% !important;
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
`;
|
|
467
|
+
shadow.appendChild(style);
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
|
|
392
473
|
if(_this.inEditing)
|
|
393
474
|
_this.inputIdentifizier();
|
|
394
475
|
else
|
|
@@ -248,7 +248,7 @@ sparnatural.addEventListener("queryUpdated", (event) => {
|
|
|
248
248
|
const queryString = sparnatural.expandSparql(event.detail.queryString);
|
|
249
249
|
|
|
250
250
|
const q = event.detail.queryJson;
|
|
251
|
-
|
|
251
|
+
// lastLiteralPredicate = extractLiteralPredicate(q);
|
|
252
252
|
|
|
253
253
|
yasqe.setValue(queryString);
|
|
254
254
|
console.log("Sparnatural JSON query:");
|
|
@@ -112,8 +112,8 @@
|
|
|
112
112
|
{% endif %}
|
|
113
113
|
|
|
114
114
|
<div id="shacl-container"
|
|
115
|
-
style="
|
|
116
|
-
<shacl-form id="shacl-form" data-collapse="open"
|
|
115
|
+
style="border:dashed 2px gray; padding:10px; border-radius:5px; max-width: 60%; margin: 0 auto; margin-top:20px;">
|
|
116
|
+
<shacl-form shadow="false" id="shacl-form" data-collapse="open"
|
|
117
117
|
data-values-namespace="indagine:"
|
|
118
118
|
data-shapes-url="/backend/ontology/schema/editing"
|
|
119
119
|
data-generate-node-shape-reference=""
|
|
@@ -1,52 +1,248 @@
|
|
|
1
1
|
{% extends "/v2/layout.twig" %}
|
|
2
2
|
|
|
3
|
+
{# --------------------------------------------------
|
|
4
|
+
Forziamo modalità viewer:
|
|
5
|
+
- niente sidebar
|
|
6
|
+
- header minimale
|
|
7
|
+
-------------------------------------------------- #}
|
|
8
|
+
{% set activeMenu = null %}
|
|
9
|
+
{% set activeSidebar = null %}
|
|
10
|
+
{% set activeSidebarItem = null %}
|
|
11
|
+
|
|
12
|
+
{% block extendHead %}
|
|
13
|
+
|
|
14
|
+
{# SHACL FORM web component #}
|
|
15
|
+
<script src="/frontend/js/lib/shacl-form.bundle-2.0.7-11.js" type="module"></script>
|
|
16
|
+
|
|
17
|
+
{# Vue investigation (stessa usata per editing) #}
|
|
18
|
+
<script src="/frontend/js/app/vue-investigation.js"></script>
|
|
19
|
+
|
|
20
|
+
<style>
|
|
21
|
+
.viewer-container {
|
|
22
|
+
max-width: 1100px;
|
|
23
|
+
margin: 20px auto;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.viewer-header {
|
|
27
|
+
display: flex;
|
|
28
|
+
justify-content: space-between;
|
|
29
|
+
align-items: center;
|
|
30
|
+
margin-bottom: 10px;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.viewer-header h2 {
|
|
34
|
+
margin: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.viewer-actions {
|
|
38
|
+
text-align: center;
|
|
39
|
+
margin-top: 20px;
|
|
40
|
+
}
|
|
41
|
+
</style>
|
|
42
|
+
|
|
43
|
+
{% endblock %}
|
|
44
|
+
|
|
3
45
|
{% block content %}
|
|
4
46
|
|
|
5
|
-
<div class="container
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
47
|
+
<div class="viewer-container">
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
{# --------------------------------------------------
|
|
52
|
+
Vue root (SENZA search)
|
|
53
|
+
UUID passato dal controller
|
|
54
|
+
-------------------------------------------------- #}
|
|
55
|
+
<div v-cloak
|
|
56
|
+
id="investigation-app"
|
|
57
|
+
data-cur_role="{{ user.role }}"
|
|
58
|
+
data-uuid="{{ uuid }}"
|
|
59
|
+
data-form-id="{{ form_id }}"
|
|
60
|
+
data-editing="false"
|
|
61
|
+
data-show-form="true"
|
|
62
|
+
data-label_save_ok="{{ t('investigation.save_ok') }}"
|
|
63
|
+
data-label_save_err="{{ t('investigation.save_err') }}"
|
|
64
|
+
>
|
|
65
|
+
|
|
66
|
+
<div class="viewer-header">
|
|
67
|
+
{% if user.role != 3 %}
|
|
68
|
+
<!-- MODIFICA -->
|
|
69
|
+
<button v-if="!inEditingViewer"
|
|
70
|
+
title="{{ t('investigation.edit_item') }}"
|
|
71
|
+
@click="startEdit"
|
|
72
|
+
type="button"
|
|
73
|
+
class="btn btn-info">
|
|
74
|
+
<i class="fa-solid fa-pen-to-square"></i>
|
|
75
|
+
</button>
|
|
76
|
+
|
|
77
|
+
<!-- STOP EDITING -->
|
|
78
|
+
<button v-if="inEditingViewer"
|
|
79
|
+
title="{{ t('investigation.stop_edit') }}"
|
|
80
|
+
@click="stopEdit"
|
|
81
|
+
type="button"
|
|
82
|
+
class="btn btn-success">
|
|
83
|
+
<i class="fa-solid fa-circle-stop" style="color:red;"></i>
|
|
84
|
+
</button>
|
|
85
|
+
|
|
86
|
+
{% endif %}
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
</div>
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
<template v-if="isVisible">
|
|
94
|
+
|
|
95
|
+
{# ---------------- BUTTONS ---------------- #}
|
|
96
|
+
{% if user.role != 3 %}
|
|
97
|
+
<div class="col-12 text-center mt-4">
|
|
98
|
+
|
|
99
|
+
<button class="btn btn-secondary mx-2"
|
|
100
|
+
@click="download('xml')">
|
|
101
|
+
RDF/XML
|
|
102
|
+
</button>
|
|
103
|
+
|
|
104
|
+
<button class="btn btn-secondary mx-2"
|
|
105
|
+
@click="download('ttl')">
|
|
106
|
+
TURTLE
|
|
107
|
+
</button>
|
|
108
|
+
|
|
109
|
+
<button v-if="inEditingViewer && validForm"
|
|
110
|
+
:disabled="saving"
|
|
111
|
+
class="btn btn-primary mx-2"
|
|
112
|
+
@click="save(false)">
|
|
113
|
+
<i v-if="saving" class="fa-solid fa-spinner"></i>
|
|
114
|
+
<i v-else class="fa-solid fa-save"></i>
|
|
115
|
+
</button>
|
|
32
116
|
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
</div>
|
|
120
|
+
{% endif %}
|
|
121
|
+
|
|
122
|
+
{# ---------------- SHACL FORM ---------------- #}
|
|
123
|
+
<div id="shacl-container"
|
|
124
|
+
style="margin-top:15px;
|
|
125
|
+
border:dashed 2px gray;
|
|
126
|
+
padding:15px;
|
|
127
|
+
border-radius:6px;">
|
|
128
|
+
|
|
129
|
+
<shacl-form id="shacl-form"
|
|
130
|
+
data-collapse="open"
|
|
131
|
+
data-values-namespace="indagine:"
|
|
132
|
+
data-shapes-url="/backend/ontology/schema/editing"
|
|
133
|
+
data-generate-node-shape-reference=""
|
|
134
|
+
></shacl-form>
|
|
135
|
+
|
|
136
|
+
</div>
|
|
137
|
+
|
|
138
|
+
{# ---------------- DEBUG OUTPUT (admin) ---------------- #}
|
|
139
|
+
{% if user.role in [0,1] %}
|
|
140
|
+
<fieldset v-if="inEditingViewer"
|
|
141
|
+
style="margin-top:15px;
|
|
142
|
+
border: solid 1px gray;
|
|
143
|
+
border-radius: 6px;
|
|
144
|
+
padding: 10px;">
|
|
145
|
+
<legend>
|
|
146
|
+
Output SHACL
|
|
147
|
+
[{@ validForm ? 'valido' : 'non valido' @}]
|
|
148
|
+
</legend>
|
|
149
|
+
<pre :style="outputStyle">{@ serializedForm @}</pre>
|
|
150
|
+
</fieldset>
|
|
151
|
+
{% endif %}
|
|
152
|
+
|
|
153
|
+
</template>
|
|
154
|
+
|
|
155
|
+
</div>
|
|
156
|
+
|
|
157
|
+
{# ---------------- CLOSE TAB ---------------- #}
|
|
158
|
+
<div class="viewer-actions">
|
|
159
|
+
<button class="btn btn-outline-secondary"
|
|
160
|
+
onclick="tryCloseViewer()">
|
|
161
|
+
Chiudi
|
|
162
|
+
</button>
|
|
163
|
+
|
|
164
|
+
<div id="close-hint"
|
|
165
|
+
style="display:none; margin-top:6px; color:#666; font-size:0.9em;">
|
|
166
|
+
Puoi chiudere questa scheda dal browser.
|
|
167
|
+
</div>
|
|
33
168
|
</div>
|
|
34
169
|
|
|
35
170
|
</div>
|
|
36
171
|
|
|
37
172
|
<script>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
173
|
+
function tryCloseViewer() {
|
|
174
|
+
window.close();
|
|
175
|
+
setTimeout(() => {
|
|
176
|
+
const hint = document.getElementById('close-hint');
|
|
177
|
+
if (hint) hint.style.display = 'block';
|
|
178
|
+
}, 200);
|
|
179
|
+
}
|
|
41
180
|
|
|
42
|
-
// rimuove readonly → entra in editing
|
|
43
|
-
form.removeAttribute('data-readonly');
|
|
44
181
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
182
|
+
async function startEditFromViewer(btn) {
|
|
183
|
+
if (btn) {
|
|
184
|
+
btn.disabled = true;
|
|
185
|
+
btn.classList.add('disabled');
|
|
186
|
+
}
|
|
50
187
|
|
|
188
|
+
const appEl = document.getElementById('investigation-app');
|
|
189
|
+
if (!appEl) return;
|
|
51
190
|
|
|
52
|
-
|
|
191
|
+
const uuid = appEl.dataset.uuid;
|
|
192
|
+
if (!uuid) {
|
|
193
|
+
alert("UUID non disponibile");
|
|
194
|
+
if (btn) btn.disabled = false;
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
try {
|
|
199
|
+
// 🔍 riuso search
|
|
200
|
+
const res = await fetch('/backend/ontology/form/search', {
|
|
201
|
+
method: 'POST',
|
|
202
|
+
headers: { 'Content-Type': 'application/json' },
|
|
203
|
+
body: JSON.stringify({ query: uuid, limit: 1 })
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
const response = await res.json();
|
|
207
|
+
|
|
208
|
+
if (!response.success || !response.data?.length) {
|
|
209
|
+
alert("Indagine non trovata");
|
|
210
|
+
if (btn) btn.disabled = false;
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const item = response.data[0];
|
|
215
|
+
|
|
216
|
+
// 🔐 lock
|
|
217
|
+
const lockResp = await fetch(
|
|
218
|
+
`/backend/ontology/form/lock/${item.id}/${window.CLIENT_UUID}`
|
|
219
|
+
).then(r => r.json());
|
|
220
|
+
|
|
221
|
+
if (!lockResp.success) {
|
|
222
|
+
alert("Indagine in modifica da un altro UTENTES");
|
|
223
|
+
if (btn) btn.disabled = false;
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// 🔥 entra in editing
|
|
228
|
+
window.dispatchEvent(
|
|
229
|
+
new CustomEvent('edit-item', {
|
|
230
|
+
detail: {
|
|
231
|
+
id: item.id,
|
|
232
|
+
uuid: item.uuid
|
|
233
|
+
}
|
|
234
|
+
})
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
} catch (e) {
|
|
238
|
+
console.error(e);
|
|
239
|
+
alert("Errore durante l'attivazione della modifica");
|
|
240
|
+
if (btn) btn.disabled = false;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
</script>
|
|
247
|
+
|
|
248
|
+
{% endblock %}
|
package/src/views/v2/layout.twig
CHANGED