@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
package/src/i18n.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import VueI18n from "vue-i18n";
|
|
3
|
-
|
|
4
|
-
Vue.use(VueI18n);
|
|
1
|
+
import { createI18n } from "vue-i18n";
|
|
5
2
|
|
|
6
3
|
function loadLocaleMessages() {
|
|
7
4
|
const locales = require.context(
|
|
@@ -20,7 +17,7 @@ function loadLocaleMessages() {
|
|
|
20
17
|
return messages;
|
|
21
18
|
}
|
|
22
19
|
|
|
23
|
-
export
|
|
20
|
+
export const i18n = createI18n({
|
|
24
21
|
locale: process.env.VUE_APP_LOCALE || "en",
|
|
25
22
|
fallbackLocale: "en",
|
|
26
23
|
messages: loadLocaleMessages(),
|
package/src/locales/de.json
CHANGED
|
@@ -166,5 +166,6 @@
|
|
|
166
166
|
"checkbox_ann_details": "Für dieses Label wird ein Kästchen extrahiert.",
|
|
167
167
|
"document_section": "Dokumentabschnitt",
|
|
168
168
|
"label_size": "Spaltengröße:",
|
|
169
|
-
"powered_by": "betrieben von Konfuzio"
|
|
169
|
+
"powered_by": "betrieben von Konfuzio",
|
|
170
|
+
"nav_label_anns": "Durch Annotationen navigieren"
|
|
170
171
|
}
|
package/src/locales/en.json
CHANGED
|
@@ -167,5 +167,6 @@
|
|
|
167
167
|
"checkbox_ann_details": "A checkbox will be extracted for this label.",
|
|
168
168
|
"document_section": "Document Section",
|
|
169
169
|
"label_size": "Column size:",
|
|
170
|
-
"powered_by": "powered by Konfuzio"
|
|
170
|
+
"powered_by": "powered by Konfuzio",
|
|
171
|
+
"nav_label_anns": "Navigate through annotations"
|
|
171
172
|
}
|
package/src/locales/es.json
CHANGED
|
@@ -166,5 +166,6 @@
|
|
|
166
166
|
"checkbox_ann_details": "Se extraerá una casilla de verificación para esta etiqueta.",
|
|
167
167
|
"document_section": "Sección del documento",
|
|
168
168
|
"label_size": "Tamaño de columna:",
|
|
169
|
-
"powered_by": "impulsado por Konfuzio"
|
|
169
|
+
"powered_by": "impulsado por Konfuzio",
|
|
170
|
+
"nav_label_anns": "Navegar por las anotaciones"
|
|
170
171
|
}
|
package/src/main.js
CHANGED
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
import App from "./components/App";
|
|
2
|
-
import
|
|
2
|
+
import { createApp } from "vue";
|
|
3
3
|
import Buefy from "buefy";
|
|
4
4
|
import VueKonva from "vue-konva";
|
|
5
|
-
import i18n from "./i18n";
|
|
6
|
-
import store from "./store";
|
|
7
|
-
import VueObserveVisibility from "
|
|
5
|
+
import { i18n } from "./i18n";
|
|
6
|
+
import { store } from "./store";
|
|
7
|
+
import VueObserveVisibility from "vue3-observe-visibility";
|
|
8
8
|
import Icons from "./icons";
|
|
9
|
-
import VueSplit from "vue-split-panel";
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
const app = createApp();
|
|
11
|
+
|
|
12
|
+
app.component("App", App);
|
|
13
|
+
app.component("VueFontawesome", Icons);
|
|
14
|
+
app.use(VueKonva);
|
|
15
|
+
app.use(Buefy, {
|
|
15
16
|
defaultIconPack: "fas",
|
|
16
17
|
defaultIconComponent: "vue-fontawesome",
|
|
17
18
|
});
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
app.use(VueObserveVisibility);
|
|
20
|
+
app.use(store);
|
|
21
|
+
app.use(i18n);
|
|
20
22
|
|
|
21
23
|
/**
|
|
22
24
|
* Main entrypoint for the App
|
|
23
25
|
*/
|
|
24
|
-
|
|
25
|
-
i18n,
|
|
26
|
-
store,
|
|
27
|
-
el: "#app",
|
|
28
|
-
});
|
|
26
|
+
app.mount("#app");
|
package/src/store/display.js
CHANGED
|
@@ -113,32 +113,43 @@ const getters = {
|
|
|
113
113
|
* image rendering.
|
|
114
114
|
*/
|
|
115
115
|
imageScale: (state) => (page) => {
|
|
116
|
-
|
|
116
|
+
if (
|
|
117
|
+
page.size &&
|
|
118
|
+
page.size.length > 0 &&
|
|
119
|
+
page.original_size &&
|
|
120
|
+
page.original_size.length > 0
|
|
121
|
+
) {
|
|
122
|
+
return new BigNumber(page.size[0]).div(page.original_size[0]).toNumber();
|
|
123
|
+
}
|
|
124
|
+
return 0;
|
|
117
125
|
},
|
|
118
126
|
bboxToPoint:
|
|
119
127
|
(state, getters) =>
|
|
120
128
|
(page, point, hasOffset = false) => {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
129
|
+
if (page && page.original_size && page.original_size.length > 1) {
|
|
130
|
+
const imageScale = getters.imageScale(page);
|
|
131
|
+
const { x, y } = point;
|
|
132
|
+
const pageHeight = new BigNumber(page.original_size[1]);
|
|
133
|
+
const newPoint = {
|
|
134
|
+
// left
|
|
135
|
+
x: new BigNumber(x)
|
|
136
|
+
.minus(hasOffset ? 1 : 0)
|
|
137
|
+
.times(state.scale)
|
|
138
|
+
.times(imageScale)
|
|
139
|
+
.div(PIXEL_RATIO)
|
|
140
|
+
.toNumber(),
|
|
141
|
+
// top
|
|
142
|
+
y: pageHeight
|
|
143
|
+
.minus(new BigNumber(y))
|
|
144
|
+
.minus(hasOffset ? 17.1 : 0)
|
|
145
|
+
.times(state.scale)
|
|
146
|
+
.times(imageScale)
|
|
147
|
+
.div(PIXEL_RATIO)
|
|
148
|
+
.toNumber(),
|
|
149
|
+
};
|
|
150
|
+
return newPoint;
|
|
151
|
+
}
|
|
152
|
+
return { x: 0, y: 0 };
|
|
142
153
|
},
|
|
143
154
|
bboxToRect:
|
|
144
155
|
(state, getters) =>
|
package/src/store/document.js
CHANGED
|
@@ -153,6 +153,31 @@ const getters = {
|
|
|
153
153
|
return annotations.length > 0;
|
|
154
154
|
},
|
|
155
155
|
|
|
156
|
+
/* Checks if the label has annotations to show */
|
|
157
|
+
isLabelMultiFalseAndGroupOfAnns: (state) => (label) => {
|
|
158
|
+
return (
|
|
159
|
+
label &&
|
|
160
|
+
label.annotations &&
|
|
161
|
+
label.annotations.length > 1 &&
|
|
162
|
+
!label.has_multiple_top_candidates &&
|
|
163
|
+
state.enableGroupingFeature
|
|
164
|
+
);
|
|
165
|
+
},
|
|
166
|
+
|
|
167
|
+
/* Returns the annotations ordered by highest confidence */
|
|
168
|
+
annotationsByConfidence: (state) => (annotations) => {
|
|
169
|
+
annotations.sort((a, b) => {
|
|
170
|
+
if (a.confidence < b.confidence) {
|
|
171
|
+
return -1;
|
|
172
|
+
} else if (a.confidence > b.confidence) {
|
|
173
|
+
return 1;
|
|
174
|
+
}
|
|
175
|
+
return 0;
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
return annotations;
|
|
179
|
+
},
|
|
180
|
+
|
|
156
181
|
/* Checks if the document has an annotation set */
|
|
157
182
|
annotationSetExists: (state) => (annotationSetId) => {
|
|
158
183
|
return state.annotationSets.find((annSet) => annSet.id === annotationSetId);
|
|
@@ -256,11 +281,16 @@ const getters = {
|
|
|
256
281
|
/* Get label for a given annotation */
|
|
257
282
|
labelOfAnnotation: (state) => (annotationToFind) => {
|
|
258
283
|
let foundLabel = null;
|
|
259
|
-
state.annotationSets
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
284
|
+
if (state.annotationSets) {
|
|
285
|
+
state.annotationSets.forEach((annotationSet) => {
|
|
286
|
+
annotationSet.labels.forEach((label) => {
|
|
287
|
+
label.annotations.forEach((annotation) => {
|
|
288
|
+
if (annotation.id === annotationToFind.id) {
|
|
289
|
+
foundLabel = label;
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
if (foundLabel) {
|
|
264
294
|
return;
|
|
265
295
|
}
|
|
266
296
|
});
|
|
@@ -268,14 +298,12 @@ const getters = {
|
|
|
268
298
|
return;
|
|
269
299
|
}
|
|
270
300
|
});
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
}
|
|
274
|
-
});
|
|
301
|
+
}
|
|
302
|
+
|
|
275
303
|
return foundLabel;
|
|
276
304
|
},
|
|
277
305
|
|
|
278
|
-
getAnnotationsFiltered: (state) => {
|
|
306
|
+
getAnnotationsFiltered: (state, getters) => {
|
|
279
307
|
// group annotations for sidebar
|
|
280
308
|
let annotations = [];
|
|
281
309
|
let labels = [];
|
|
@@ -331,6 +359,18 @@ const getters = {
|
|
|
331
359
|
return false;
|
|
332
360
|
};
|
|
333
361
|
|
|
362
|
+
const sortByConfidenceOrByAnnotationSelected = (annotations) => {
|
|
363
|
+
annotations = getters.annotationsByConfidence(annotations);
|
|
364
|
+
if (state.annotationId) {
|
|
365
|
+
for (let i = 0; i < annotations.length; i++) {
|
|
366
|
+
if (state.annotationId == annotations[i].id) {
|
|
367
|
+
annotations.unshift(annotations.splice(i, 1)[0]);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return annotations;
|
|
372
|
+
};
|
|
373
|
+
|
|
334
374
|
if (state.annotationSets) {
|
|
335
375
|
state.annotationSets.forEach((annotationSet) => {
|
|
336
376
|
labels = [];
|
|
@@ -350,6 +390,13 @@ const getters = {
|
|
|
350
390
|
!state.annotationFilters.showFeedbackNeeded ||
|
|
351
391
|
!state.annotationFilters.showAccepted
|
|
352
392
|
) {
|
|
393
|
+
if (!label.has_multiple_top_candidates) {
|
|
394
|
+
// if multi label = false, sort by confidence
|
|
395
|
+
label.annotations = sortByConfidenceOrByAnnotationSelected(
|
|
396
|
+
label.annotations
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
|
|
353
400
|
label.annotations.forEach((annotation) => {
|
|
354
401
|
if (
|
|
355
402
|
state.annotationFilters.showFeedbackNeeded &&
|
|
@@ -379,6 +426,12 @@ const getters = {
|
|
|
379
426
|
}
|
|
380
427
|
});
|
|
381
428
|
} else {
|
|
429
|
+
if (!label.has_multiple_top_candidates) {
|
|
430
|
+
// if multi label = false, sort by confidence
|
|
431
|
+
label.annotations = sortByConfidenceOrByAnnotationSelected(
|
|
432
|
+
label.annotations
|
|
433
|
+
);
|
|
434
|
+
}
|
|
382
435
|
// add annotations to the document array
|
|
383
436
|
label.annotations.forEach((annotation) => {
|
|
384
437
|
const added = addAnnotation(
|
|
@@ -963,6 +1016,15 @@ const actions = {
|
|
|
963
1016
|
commit("SET_DOC_ID", id);
|
|
964
1017
|
},
|
|
965
1018
|
setAnnotationId: ({ commit, dispatch, getters }, id) => {
|
|
1019
|
+
if (id) {
|
|
1020
|
+
// check if part of label with multi ann as false
|
|
1021
|
+
const annotation = getters.annotationById(id);
|
|
1022
|
+
const label = getters.labelOfAnnotation(annotation);
|
|
1023
|
+
if (getters.isLabelMultiFalseAndGroupOfAnns(label)) {
|
|
1024
|
+
dispatch("setAnnotationAsFirstInLabel", { label, annotation });
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
|
|
966
1028
|
commit("SET_ANNOTATION_ID", id);
|
|
967
1029
|
setURLAnnotationHash(id);
|
|
968
1030
|
},
|
|
@@ -1134,6 +1196,7 @@ const actions = {
|
|
|
1134
1196
|
// Check if we first open the document dashboard or the edit mode
|
|
1135
1197
|
if (
|
|
1136
1198
|
!state.publicView &&
|
|
1199
|
+
state.selectedDocument &&
|
|
1137
1200
|
(!state.selectedDocument.category ||
|
|
1138
1201
|
(!state.selectedDocument.category_is_revised &&
|
|
1139
1202
|
!getters.documentHasCorrectAnnotations &&
|
|
@@ -1541,6 +1604,57 @@ const actions = {
|
|
|
1541
1604
|
showAcceptedAnnotations({ commit }, show) {
|
|
1542
1605
|
commit("SET_SHOW_ACCEPTED_ANNOTATIONS", show);
|
|
1543
1606
|
},
|
|
1607
|
+
setAnnotationAsFirstInLabel({ commit, state }, { label, annotation }) {
|
|
1608
|
+
state.annotationSets.forEach((annotationSet) => {
|
|
1609
|
+
annotationSet.labels.forEach((labelToFind) => {
|
|
1610
|
+
if (labelToFind.id === label.id) {
|
|
1611
|
+
if (labelToFind.annotations && labelToFind.annotations.length > 1) {
|
|
1612
|
+
for (let i = 0; i < labelToFind.annotations.length; i++) {
|
|
1613
|
+
if (labelToFind.annotations[i].id === annotation.id) {
|
|
1614
|
+
labelToFind.annotations.unshift(
|
|
1615
|
+
labelToFind.annotations.splice(i, 1)[0]
|
|
1616
|
+
);
|
|
1617
|
+
commit("SET_ANNOTATIONS_IN_LABEL", {
|
|
1618
|
+
label: labelToFind,
|
|
1619
|
+
annotations: labelToFind.annotations,
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
}
|
|
1625
|
+
});
|
|
1626
|
+
});
|
|
1627
|
+
},
|
|
1628
|
+
putNextAnnotationInLabelFirst({ commit, state, dispatch }, label) {
|
|
1629
|
+
dispatch("setAnnotationId", null);
|
|
1630
|
+
let newFirstAnn = null;
|
|
1631
|
+
state.annotationSets.forEach((annotationSet) => {
|
|
1632
|
+
annotationSet.labels.forEach((labelToFind) => {
|
|
1633
|
+
if (labelToFind.id === label.id) {
|
|
1634
|
+
if (labelToFind.annotations && labelToFind.annotations.length > 1) {
|
|
1635
|
+
const firstElement = labelToFind.annotations.shift();
|
|
1636
|
+
labelToFind.annotations.push(firstElement);
|
|
1637
|
+
commit("SET_ANNOTATIONS_IN_LABEL", {
|
|
1638
|
+
label: labelToFind,
|
|
1639
|
+
annotations: labelToFind.annotations,
|
|
1640
|
+
});
|
|
1641
|
+
newFirstAnn = labelToFind.annotations[0];
|
|
1642
|
+
}
|
|
1643
|
+
}
|
|
1644
|
+
});
|
|
1645
|
+
});
|
|
1646
|
+
|
|
1647
|
+
if (newFirstAnn) {
|
|
1648
|
+
dispatch("setDocumentAnnotationSelected", {
|
|
1649
|
+
annotation: newFirstAnn,
|
|
1650
|
+
label: label,
|
|
1651
|
+
span: newFirstAnn.span[0],
|
|
1652
|
+
scrollTo: true,
|
|
1653
|
+
});
|
|
1654
|
+
|
|
1655
|
+
dispatch("scrollToDocumentAnnotationSelected");
|
|
1656
|
+
}
|
|
1657
|
+
},
|
|
1544
1658
|
};
|
|
1545
1659
|
|
|
1546
1660
|
const mutations = {
|
|
@@ -1686,6 +1800,13 @@ const mutations = {
|
|
|
1686
1800
|
SET_LABELS: (state, labels) => {
|
|
1687
1801
|
state.labels = labels;
|
|
1688
1802
|
},
|
|
1803
|
+
SET_ANNOTATIONS_IN_LABEL: (state, { label, annotations }) => {
|
|
1804
|
+
state.labels.forEach((labelToFind) => {
|
|
1805
|
+
if (labelToFind.id === label.id) {
|
|
1806
|
+
labelToFind.annotations = annotations;
|
|
1807
|
+
}
|
|
1808
|
+
});
|
|
1809
|
+
},
|
|
1689
1810
|
SET_EDIT_ANNOTATION: (state, editAnnotation) => {
|
|
1690
1811
|
state.editAnnotation = editAnnotation;
|
|
1691
1812
|
},
|
package/src/store/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Vuex from "vuex";
|
|
1
|
+
import { createStore } from "vuex";
|
|
3
2
|
|
|
4
3
|
import display from "./display";
|
|
5
4
|
import document from "./document";
|
|
@@ -8,15 +7,13 @@ import project from "./project";
|
|
|
8
7
|
import selection from "./selection";
|
|
9
8
|
import edit from "./edit";
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export default new Vuex.Store({
|
|
10
|
+
export const store = createStore({
|
|
14
11
|
modules: {
|
|
15
12
|
display,
|
|
16
13
|
document,
|
|
17
14
|
category,
|
|
18
15
|
project,
|
|
19
16
|
selection,
|
|
20
|
-
edit
|
|
21
|
-
}
|
|
22
|
-
});
|
|
17
|
+
edit,
|
|
18
|
+
},
|
|
19
|
+
});
|