@konfuzio/document-validation-ui 0.1.59 → 0.2.0-dev.2
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/cypress.config.js +6 -6
- package/dist/css/app.css +1 -1
- package/dist/index.html +1 -1
- package/dist/js/app.js +1 -1
- package/dist/js/app.js.map +1 -1
- package/dist/js/chunk-vendors.js +66 -23
- package/dist/js/chunk-vendors.js.map +1 -1
- package/jest.config.js +22 -2
- package/package.json +32 -38
- package/src/assets/scss/ann_set_table_options.scss +4 -4
- package/src/assets/scss/annotation_action_buttons.scss +29 -7
- package/src/assets/scss/annotation_details.scss +9 -9
- package/src/assets/scss/choose_label_set_modal.scss +5 -5
- package/src/assets/scss/document_action_bar.scss +3 -3
- package/src/assets/scss/document_annotations.scss +45 -45
- package/src/assets/scss/document_category.scss +8 -8
- package/src/assets/scss/document_dashboard.scss +6 -1
- package/src/assets/scss/document_edit.scss +30 -30
- package/src/assets/scss/document_error.scss +6 -6
- package/src/assets/scss/document_name.scss +6 -6
- package/src/assets/scss/document_page.scss +3 -3
- package/src/assets/scss/document_search_bar.scss +7 -7
- package/src/assets/scss/document_set_chooser.scss +3 -3
- package/src/assets/scss/document_thumbnails.scss +7 -7
- package/src/assets/scss/document_toolbar.scss +10 -10
- package/src/assets/scss/document_top_bar.scss +11 -11
- package/src/assets/scss/document_viewport_modal.scss +3 -3
- package/src/assets/scss/documents_list.scss +11 -12
- package/src/assets/scss/edit_page_thumbnail.scss +6 -6
- package/src/assets/scss/empty_state.scss +4 -4
- package/src/assets/scss/error_page.scss +2 -2
- package/src/assets/scss/extracting_data.scss +3 -3
- package/src/assets/scss/multi_ann_table_overlay.scss +3 -3
- package/src/assets/scss/multi_ann_table_popup.scss +1 -1
- package/src/assets/scss/new_annotation.scss +25 -19
- package/src/assets/scss/scrolling_document.scss +1 -1
- package/src/assets/scss/theme.scss +64 -52
- package/src/assets/scss/variables.scss +2 -0
- package/src/components/App.vue +9 -14
- package/src/components/DocumentAnnotations/AnnotationActionButtons.vue +31 -7
- package/src/components/DocumentAnnotations/AnnotationContent.vue +25 -52
- package/src/components/DocumentAnnotations/AnnotationRow.vue +108 -51
- package/src/components/DocumentAnnotations/DocumentAnnotations.vue +12 -6
- package/src/components/DocumentAnnotations/DocumentLabel.vue +12 -122
- package/src/components/DocumentAnnotations/EmptyAnnotation.vue +31 -70
- package/src/components/DocumentDashboard.vue +12 -17
- package/src/components/DocumentEdit/EditPages.vue +51 -46
- package/src/components/DocumentEdit/EditSidebar.vue +0 -9
- package/src/components/DocumentPage/{NewAnnotation.vue → AnnotationPopup.vue} +123 -94
- package/src/components/DocumentPage/BoxSelection.vue +16 -49
- package/src/components/DocumentPage/DocumentPage.vue +56 -153
- package/src/components/DocumentPage/DocumentToolbar.vue +0 -1
- package/src/components/DocumentPage/PlaceholderSelection.vue +51 -0
- package/src/components/DocumentPage/SpanSelection.vue +259 -0
- package/src/components/DocumentThumbnails/LoadingThumbnail.vue +3 -6
- package/src/components/DocumentTopBar/DocumentTopBar.vue +4 -2
- package/src/constants.js +1 -7
- package/src/i18n.js +2 -5
- package/src/locales/de.json +2 -1
- package/src/locales/en.json +2 -1
- package/src/locales/es.json +2 -1
- package/src/main.js +14 -16
- package/src/store/display.js +33 -22
- package/src/store/document.js +131 -10
- package/src/store/index.js +5 -8
- package/src/store/selection.js +152 -76
- package/src/assets/scss/imports.scss +0 -1
- package/src/components/DocumentPage/EditAnnotation.vue +0 -372
|
@@ -1,10 +1,25 @@
|
|
|
1
1
|
<!-- eslint-disable vue/no-v-html -->
|
|
2
2
|
<template>
|
|
3
|
-
<div
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
<div
|
|
4
|
+
class="annotation-popup"
|
|
5
|
+
:style="{
|
|
6
|
+
left: `${left}px`,
|
|
7
|
+
top: `${top}px`,
|
|
8
|
+
height: `${heightOfPopup}px`,
|
|
9
|
+
}"
|
|
10
|
+
>
|
|
11
|
+
<div v-if="!editAnnotation">
|
|
12
|
+
<div v-if="spanLoading" class="popup-input">
|
|
13
|
+
<b-icon icon="spinner" class="fa-spin loading-icon-size spinner" />
|
|
14
|
+
</div>
|
|
15
|
+
<input
|
|
16
|
+
v-else
|
|
17
|
+
v-model="textFromEntities"
|
|
18
|
+
class="popup-input"
|
|
19
|
+
type="text"
|
|
20
|
+
:disabled="true"
|
|
21
|
+
/>
|
|
6
22
|
</div>
|
|
7
|
-
<input v-else v-model="textFromEntities" class="popup-input" type="text" />
|
|
8
23
|
<b-dropdown
|
|
9
24
|
v-model="selectedSet"
|
|
10
25
|
:disabled="!textFromEntities"
|
|
@@ -27,17 +42,19 @@
|
|
|
27
42
|
]"
|
|
28
43
|
type="is-text"
|
|
29
44
|
>
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
45
|
+
<span class="input-text">
|
|
46
|
+
{{
|
|
47
|
+
selectedSet
|
|
48
|
+
? `${selectedSet.label_set.name} ${
|
|
49
|
+
selectedSet.id
|
|
50
|
+
? numberOfAnnotationSetGroup(selectedSet)
|
|
51
|
+
: `${numberOfLabelSetGroup(selectedSet.label_set)} (${$t(
|
|
52
|
+
"new"
|
|
53
|
+
)})`
|
|
54
|
+
}`
|
|
55
|
+
: $t("select_annotation_set")
|
|
56
|
+
}}</span
|
|
57
|
+
>
|
|
41
58
|
<span class="caret-icon">
|
|
42
59
|
<b-icon icon="angle-down" size="is-small" class="caret" />
|
|
43
60
|
</span>
|
|
@@ -72,7 +89,6 @@
|
|
|
72
89
|
size="is-large"
|
|
73
90
|
position="is-bottom"
|
|
74
91
|
class="bottom-aligned"
|
|
75
|
-
:close-delay="5000"
|
|
76
92
|
>
|
|
77
93
|
<template #content>
|
|
78
94
|
<div
|
|
@@ -99,13 +115,13 @@
|
|
|
99
115
|
]"
|
|
100
116
|
type="is-text"
|
|
101
117
|
>
|
|
102
|
-
{{
|
|
118
|
+
<span class="input-text">{{
|
|
103
119
|
selectedLabel
|
|
104
120
|
? selectedLabel.name
|
|
105
121
|
: labels && labels.length === 0
|
|
106
122
|
? $t("no_labels_to_choose")
|
|
107
123
|
: $t("select_label")
|
|
108
|
-
}}
|
|
124
|
+
}}</span>
|
|
109
125
|
<span class="caret-icon">
|
|
110
126
|
<b-icon icon="angle-down" size="is-small" class="caret" />
|
|
111
127
|
</span>
|
|
@@ -144,15 +160,12 @@
|
|
|
144
160
|
* This component is used to show a popup
|
|
145
161
|
* for creating a new annotation.
|
|
146
162
|
*/
|
|
147
|
-
const heightOfPopup = 192;
|
|
148
|
-
const margin = 12;
|
|
149
|
-
const widthOfPopup = 205;
|
|
150
163
|
|
|
151
164
|
import { mapGetters, mapState } from "vuex";
|
|
152
165
|
|
|
153
166
|
export default {
|
|
154
167
|
props: {
|
|
155
|
-
|
|
168
|
+
spans: {
|
|
156
169
|
required: true,
|
|
157
170
|
type: Array,
|
|
158
171
|
},
|
|
@@ -171,6 +184,9 @@ export default {
|
|
|
171
184
|
},
|
|
172
185
|
data() {
|
|
173
186
|
return {
|
|
187
|
+
heightOfPopup: 192,
|
|
188
|
+
margin: 12,
|
|
189
|
+
widthOfPopup: 205,
|
|
174
190
|
selectedLabel: null,
|
|
175
191
|
selectedSet: null,
|
|
176
192
|
labels: null,
|
|
@@ -180,51 +196,48 @@ export default {
|
|
|
180
196
|
};
|
|
181
197
|
},
|
|
182
198
|
computed: {
|
|
183
|
-
...mapState("document", ["annotationSets", "documentId"]),
|
|
199
|
+
...mapState("document", ["annotationSets", "documentId", "editAnnotation"]),
|
|
184
200
|
...mapGetters("document", [
|
|
185
201
|
"numberOfAnnotationSetGroup",
|
|
186
202
|
"numberOfLabelSetGroup",
|
|
187
203
|
"labelsFilteredForAnnotationCreation",
|
|
188
204
|
]),
|
|
189
205
|
...mapState("display", ["showBranding"]),
|
|
190
|
-
...mapGetters("display", ["clientToBbox"]),
|
|
191
|
-
...mapState("selection", ["spanSelection", "selection"]),
|
|
206
|
+
...mapGetters("display", ["clientToBbox", "bboxToRect"]),
|
|
207
|
+
...mapState("selection", ["spanSelection", "selection", "spanLoading"]),
|
|
192
208
|
top() {
|
|
193
209
|
if (this.selection && this.selection.end) {
|
|
194
|
-
const top = this.selection.end.y + margin;
|
|
210
|
+
const top = this.selection.end.y + this.margin;
|
|
195
211
|
//check if the popup will not go off the container on the top
|
|
196
|
-
return top + heightOfPopup < this.containerHeight
|
|
212
|
+
return top + this.heightOfPopup < this.containerHeight
|
|
197
213
|
? top
|
|
198
|
-
: this.selection.end.y - heightOfPopup;
|
|
214
|
+
: this.selection.end.y - this.heightOfPopup;
|
|
199
215
|
} else {
|
|
200
|
-
const
|
|
216
|
+
const normalizedSpan = this.bboxToRect(this.page, this.spans[0]);
|
|
217
|
+
const top = normalizedSpan.y - this.heightOfPopup; // subtract the height of the popup plus some margin
|
|
201
218
|
|
|
202
219
|
//check if the popup will not go off the container on the top
|
|
203
|
-
return
|
|
220
|
+
return normalizedSpan.y > this.heightOfPopup
|
|
204
221
|
? top
|
|
205
|
-
:
|
|
206
|
-
this.newAnnotation[0].scaled.height +
|
|
207
|
-
margin;
|
|
222
|
+
: normalizedSpan.y + normalizedSpan.height + this.margin;
|
|
208
223
|
}
|
|
209
224
|
},
|
|
210
225
|
left() {
|
|
211
226
|
if (this.selection && this.selection.start && this.selection.end) {
|
|
212
227
|
const left = this.selection.start.x;
|
|
213
228
|
//check if the popup will not go off the container on the right
|
|
214
|
-
return left + widthOfPopup < this.containerWidth
|
|
229
|
+
return left + this.widthOfPopup < this.containerWidth
|
|
215
230
|
? left
|
|
216
|
-
: this.containerWidth - widthOfPopup;
|
|
217
|
-
return this.selection.start.x;
|
|
231
|
+
: this.containerWidth - this.widthOfPopup;
|
|
218
232
|
} else {
|
|
233
|
+
const normalizedSpan = this.bboxToRect(this.page, this.spans[0]);
|
|
219
234
|
const left =
|
|
220
|
-
|
|
221
|
-
this.newAnnotation[0].scaled.width / 2 -
|
|
222
|
-
widthOfPopup / 2; // add the entity half width to be centered and then subtract half the width of the popup
|
|
235
|
+
normalizedSpan.x + normalizedSpan.width / 2 - this.widthOfPopup / 2; // add the entity half width to be centered and then subtract half the width of the popup
|
|
223
236
|
|
|
224
237
|
//check if the popup will not go off the container
|
|
225
|
-
if (left + widthOfPopup > this.containerWidth) {
|
|
238
|
+
if (left + this.widthOfPopup > this.containerWidth) {
|
|
226
239
|
// on the right side
|
|
227
|
-
return this.containerWidth - widthOfPopup;
|
|
240
|
+
return this.containerWidth - this.widthOfPopup;
|
|
228
241
|
} else {
|
|
229
242
|
// on the left side
|
|
230
243
|
return left > 0 ? left : 0;
|
|
@@ -232,10 +245,8 @@ export default {
|
|
|
232
245
|
}
|
|
233
246
|
},
|
|
234
247
|
textFromEntities() {
|
|
235
|
-
if (!this.spanSelection) return;
|
|
236
|
-
|
|
237
248
|
let text = "";
|
|
238
|
-
this.
|
|
249
|
+
this.spans.forEach((span) => {
|
|
239
250
|
text = `${text} ${span.offset_string}`;
|
|
240
251
|
});
|
|
241
252
|
|
|
@@ -243,17 +254,23 @@ export default {
|
|
|
243
254
|
},
|
|
244
255
|
},
|
|
245
256
|
watch: {
|
|
246
|
-
selectedSet(newValue) {
|
|
257
|
+
selectedSet(newValue, oldValue) {
|
|
247
258
|
this.selectedLabel = null;
|
|
248
259
|
this.labels = this.labelsFilteredForAnnotationCreation(newValue);
|
|
249
|
-
if (
|
|
260
|
+
if (oldValue === null && this.editAnnotation) {
|
|
261
|
+
this.selectedLabel = this.editAnnotation.label;
|
|
262
|
+
} else if (this.labels.length === 1) {
|
|
250
263
|
this.selectedLabel = this.labels[0];
|
|
251
264
|
}
|
|
252
265
|
},
|
|
253
266
|
},
|
|
254
267
|
mounted() {
|
|
255
268
|
this.setsList = this.orderedSetList([...this.annotationSets]);
|
|
256
|
-
|
|
269
|
+
|
|
270
|
+
if (this.editAnnotation) {
|
|
271
|
+
this.heightOfPopup = 142;
|
|
272
|
+
this.selectedSet = this.editAnnotation.annotationSet;
|
|
273
|
+
} else if (this.setsList.length === 1) {
|
|
257
274
|
this.selectedSet = this.setsList[0];
|
|
258
275
|
}
|
|
259
276
|
|
|
@@ -262,7 +279,7 @@ export default {
|
|
|
262
279
|
document.body.addEventListener("click", this.clickOutside);
|
|
263
280
|
}, 200);
|
|
264
281
|
},
|
|
265
|
-
|
|
282
|
+
unmounted() {
|
|
266
283
|
document.body.removeEventListener("click", this.clickOutside);
|
|
267
284
|
},
|
|
268
285
|
methods: {
|
|
@@ -283,61 +300,73 @@ export default {
|
|
|
283
300
|
return setsList;
|
|
284
301
|
},
|
|
285
302
|
close() {
|
|
286
|
-
this
|
|
287
|
-
|
|
303
|
+
if (this.editAnnotation) {
|
|
304
|
+
this.$store.dispatch("document/resetEditAnnotation");
|
|
305
|
+
}
|
|
306
|
+
this.$store.dispatch("selection/disableSelection");
|
|
288
307
|
this.$emit("close");
|
|
289
308
|
},
|
|
290
309
|
save() {
|
|
291
|
-
this.
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
310
|
+
if (this.editAnnotation) {
|
|
311
|
+
this.loading = true;
|
|
312
|
+
this.$store.dispatch("document/setEditAnnotation", {
|
|
313
|
+
id: this.editAnnotation.id,
|
|
314
|
+
index: this.editAnnotation.index,
|
|
315
|
+
label: this.selectedLabel,
|
|
316
|
+
labelSet: this.selectedSet.label_set,
|
|
317
|
+
annotationSet: this.selectedSet,
|
|
318
|
+
pageNumber: this.editAnnotation.pageNumber,
|
|
319
|
+
});
|
|
298
320
|
|
|
299
|
-
|
|
321
|
+
document.getElementById("save-ann").click();
|
|
300
322
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
this.selection.start,
|
|
305
|
-
this.selection.end
|
|
306
|
-
);
|
|
307
|
-
}
|
|
323
|
+
return;
|
|
324
|
+
} else {
|
|
325
|
+
this.loading = true;
|
|
308
326
|
|
|
309
|
-
|
|
310
|
-
document: this.documentId,
|
|
311
|
-
span: span,
|
|
312
|
-
label: this.selectedLabel.id,
|
|
313
|
-
is_correct: true,
|
|
314
|
-
revised: false,
|
|
315
|
-
};
|
|
327
|
+
let selection_bbox = null;
|
|
316
328
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
329
|
+
if (this.selection && this.selection.start && this.selection.end) {
|
|
330
|
+
selection_bbox = this.clientToBbox(
|
|
331
|
+
this.page,
|
|
332
|
+
this.selection.start,
|
|
333
|
+
this.selection.end
|
|
334
|
+
);
|
|
335
|
+
}
|
|
320
336
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
337
|
+
const annotationToCreate = {
|
|
338
|
+
document: this.documentId,
|
|
339
|
+
span: this.spans,
|
|
340
|
+
label: this.selectedLabel.id,
|
|
341
|
+
is_correct: true,
|
|
342
|
+
revised: false,
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
if (selection_bbox) {
|
|
346
|
+
annotationToCreate.selection_bbox = selection_bbox;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (this.selectedSet.id) {
|
|
350
|
+
annotationToCreate.annotation_set = this.selectedSet.id;
|
|
351
|
+
} else {
|
|
352
|
+
annotationToCreate.label_set = this.selectedSet.label_set.id;
|
|
353
|
+
}
|
|
354
|
+
this.$store
|
|
355
|
+
.dispatch("document/createAnnotation", {
|
|
356
|
+
annotation: annotationToCreate,
|
|
357
|
+
})
|
|
358
|
+
.catch((error) => {
|
|
359
|
+
this.$store.dispatch("document/createErrorMessage", {
|
|
360
|
+
error,
|
|
361
|
+
serverErrorMessage: this.$t("server_error"),
|
|
362
|
+
defaultErrorMessage: this.$t("error_creating_annotation"),
|
|
363
|
+
});
|
|
364
|
+
})
|
|
365
|
+
.finally(() => {
|
|
366
|
+
this.close();
|
|
367
|
+
this.loading = false;
|
|
335
368
|
});
|
|
336
|
-
|
|
337
|
-
.finally(() => {
|
|
338
|
-
this.close();
|
|
339
|
-
this.loading = false;
|
|
340
|
-
});
|
|
369
|
+
}
|
|
341
370
|
},
|
|
342
371
|
chooseLabelSet(labelSet) {
|
|
343
372
|
// check if there's already a new entry for that label set to be created
|
|
@@ -13,11 +13,6 @@
|
|
|
13
13
|
ref="boxTransformer"
|
|
14
14
|
:config="transformerConfig"
|
|
15
15
|
/>
|
|
16
|
-
<v-rect
|
|
17
|
-
v-if="selection.placeholderBox"
|
|
18
|
-
ref="placeholderSelection"
|
|
19
|
-
:config="placeholderConfig"
|
|
20
|
-
/>
|
|
21
16
|
</v-group>
|
|
22
17
|
</template>
|
|
23
18
|
|
|
@@ -56,21 +51,7 @@ export default {
|
|
|
56
51
|
draggable: true,
|
|
57
52
|
};
|
|
58
53
|
},
|
|
59
|
-
|
|
60
|
-
return {
|
|
61
|
-
x: this.selection.placeholderBox.x,
|
|
62
|
-
y: this.selection.placeholderBox.y,
|
|
63
|
-
width: this.selection.placeholderBox.width,
|
|
64
|
-
height: this.selection.placeholderBox.height,
|
|
65
|
-
fill: "transparent",
|
|
66
|
-
stroke: "#41af85",
|
|
67
|
-
strokeWidth: 3,
|
|
68
|
-
globalCompositeOperation: "multiply",
|
|
69
|
-
shadowForStrokeEnabled: false,
|
|
70
|
-
name: "placeholderSelection",
|
|
71
|
-
draggable: false,
|
|
72
|
-
};
|
|
73
|
-
},
|
|
54
|
+
|
|
74
55
|
transformerConfig() {
|
|
75
56
|
return {
|
|
76
57
|
borderEnabled: false,
|
|
@@ -87,7 +68,8 @@ export default {
|
|
|
87
68
|
"elementSelected",
|
|
88
69
|
"spanSelection",
|
|
89
70
|
]),
|
|
90
|
-
...
|
|
71
|
+
...mapState("document", ["editAnnotation"]),
|
|
72
|
+
...mapGetters("display", ["clientToBbox", "scaledEntities"]),
|
|
91
73
|
...mapGetters("selection", ["isSelectionValid", "entitiesOnSelection"]),
|
|
92
74
|
},
|
|
93
75
|
watch: {
|
|
@@ -106,19 +88,19 @@ export default {
|
|
|
106
88
|
},
|
|
107
89
|
methods: {
|
|
108
90
|
handleSelection() {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
this.entitiesOnSelection(box, this.page)
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
91
|
+
const box = this.clientToBbox(
|
|
92
|
+
this.page,
|
|
93
|
+
this.selection.start,
|
|
94
|
+
this.selection.end
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
this.$store.dispatch("selection/entitySelection", {
|
|
98
|
+
entities: this.scaledEntities(
|
|
99
|
+
this.entitiesOnSelection(box, this.page),
|
|
100
|
+
this.page
|
|
101
|
+
),
|
|
102
|
+
selection: box,
|
|
103
|
+
});
|
|
122
104
|
},
|
|
123
105
|
updateTransformer() {
|
|
124
106
|
// here we need to manually attach or detach Transformer node
|
|
@@ -152,21 +134,6 @@ export default {
|
|
|
152
134
|
transformerNode.getLayer().batchDraw();
|
|
153
135
|
},
|
|
154
136
|
|
|
155
|
-
getBoxSelectionContent() {
|
|
156
|
-
if (!this.isSelecting) {
|
|
157
|
-
const box = this.clientToBbox(
|
|
158
|
-
this.page,
|
|
159
|
-
this.selection.start,
|
|
160
|
-
this.selection.end
|
|
161
|
-
);
|
|
162
|
-
this.$emit("selectEntities", this.entitiesOnSelection(box, this.page));
|
|
163
|
-
this.$store.dispatch("selection/getTextFromBboxes", {
|
|
164
|
-
box,
|
|
165
|
-
entities: false,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
},
|
|
169
|
-
|
|
170
137
|
/**
|
|
171
138
|
* This method is used for both transforms and drags since it just
|
|
172
139
|
* retrieves the rect's new attributes from the event and uses those
|