@konfuzio/document-validation-ui 0.1.13-dev.3 → 0.1.13
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/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 +1 -1
- package/dist/js/chunk-vendors.js.map +1 -1
- package/package.json +1 -1
- package/src/.DS_Store +0 -0
- package/src/api.js +13 -9
- package/src/assets/images/ServerImage.vue +1 -1
- package/src/assets/scss/document_annotations.scss +199 -183
- package/src/assets/scss/document_thumbnails.scss +1 -1
- package/src/assets/scss/document_toolbar.scss +21 -7
- package/src/assets/scss/theme.scss +22 -0
- package/src/components/App.cy.js +1 -1
- package/src/components/App.vue +1 -1
- package/src/components/DocumentAnnotations/AnnotationDetails.vue +1 -1
- package/src/components/DocumentAnnotations/DocumentAnnotations.vue +37 -12
- package/src/components/DocumentAnnotations/DocumentLabel.vue +2 -2
- package/src/components/DocumentAnnotations/ExtractingData.vue +15 -3
- package/src/components/DocumentEdit/DocumentEdit.vue +5 -1
- package/src/components/DocumentModals/DocumentErrorModal.vue +1 -1
- package/src/components/DocumentPage/DocumentPage.vue +1 -1
- package/src/components/DocumentPage/DocumentToolbar.vue +56 -0
- package/src/components/DocumentThumbnails/DocumentThumbnails.cy.js +64 -0
- package/src/components/DocumentThumbnails/DocumentThumbnails.vue +2 -2
- package/src/icons.js +3 -1
- package/src/locales/de.json +9 -1
- package/src/locales/en.json +9 -1
- package/src/locales/es.json +9 -1
- package/src/store/document.js +4 -2
- package/src/store/edit.js +8 -0
- package/src/store/project.js +1 -1
- package/src/utils/utils.js +2 -0
|
@@ -54,7 +54,10 @@
|
|
|
54
54
|
)}`
|
|
55
55
|
}}
|
|
56
56
|
</div>
|
|
57
|
-
<div
|
|
57
|
+
<div
|
|
58
|
+
class="labelset-action-buttons"
|
|
59
|
+
v-if="annotationSet.labels.length !== 0"
|
|
60
|
+
>
|
|
58
61
|
<AnnotationSetActionButtons
|
|
59
62
|
:number-of-empty-labels-in-annotation-set="
|
|
60
63
|
emptyLabelsLength(annotationSet)
|
|
@@ -82,19 +85,33 @@
|
|
|
82
85
|
</div>
|
|
83
86
|
</div>
|
|
84
87
|
|
|
85
|
-
<div v-
|
|
86
|
-
<div
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
88
|
+
<div v-if="annotationSet.labels.length > 0">
|
|
89
|
+
<div v-for="label in annotationSet.labels" :key="label.id">
|
|
90
|
+
<div
|
|
91
|
+
v-if="!(label.annotations.length === 0 && publicView)"
|
|
92
|
+
class="labels"
|
|
93
|
+
>
|
|
94
|
+
<DocumentLabel
|
|
95
|
+
:label="label"
|
|
96
|
+
:annotation-set="annotationSet"
|
|
97
|
+
:index-group="indexGroup"
|
|
98
|
+
@handle-missing-annotation="markAnnotationsAsMissing"
|
|
99
|
+
/>
|
|
100
|
+
</div>
|
|
96
101
|
</div>
|
|
97
102
|
</div>
|
|
103
|
+
|
|
104
|
+
<div v-if="annotationSet.labels.length === 0" class="no-labels">
|
|
105
|
+
<span> {{ $t("no_labels_in_set") }}</span>
|
|
106
|
+
<span v-if="!publicView" v-html="$t('link_to_add_labels')"></span>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
<div
|
|
110
|
+
v-else-if="!annotationSetHasAnnotations(annotationSet) && publicView"
|
|
111
|
+
class="no-labels"
|
|
112
|
+
>
|
|
113
|
+
<span> {{ $t("no_annotations_in_annotation_set") }}</span>
|
|
114
|
+
</div>
|
|
98
115
|
</div>
|
|
99
116
|
</div>
|
|
100
117
|
</div>
|
|
@@ -175,6 +192,14 @@ export default {
|
|
|
175
192
|
window.removeEventListener("keydown", this.keyDownHandler);
|
|
176
193
|
},
|
|
177
194
|
methods: {
|
|
195
|
+
annotationSetHasAnnotations(annotationSet) {
|
|
196
|
+
const found = annotationSet.labels.find(
|
|
197
|
+
(label) => label.annotations.length > 0
|
|
198
|
+
);
|
|
199
|
+
|
|
200
|
+
return found;
|
|
201
|
+
},
|
|
202
|
+
|
|
178
203
|
focusOnNextAnnotation() {
|
|
179
204
|
const annotations = this.createArray("keyboard-nav");
|
|
180
205
|
|
|
@@ -15,14 +15,14 @@
|
|
|
15
15
|
</div>
|
|
16
16
|
</div>
|
|
17
17
|
<div class="label-group-right">
|
|
18
|
-
<div
|
|
18
|
+
<div class="label-annotations-pending" v-if="!publicView">
|
|
19
19
|
{{
|
|
20
20
|
`${
|
|
21
21
|
label.annotations.length - acceptedAnnotationsGroupCounter
|
|
22
22
|
} ${$t("annotations_pending")}`
|
|
23
23
|
}}
|
|
24
24
|
</div>
|
|
25
|
-
<div
|
|
25
|
+
<div class="label-annotations-accepted" v-if="!publicView">
|
|
26
26
|
{{
|
|
27
27
|
`${acceptedAnnotationsGroupCounter} ${$t("annotations_accepted")}`
|
|
28
28
|
}}
|
|
@@ -9,21 +9,33 @@
|
|
|
9
9
|
</div>
|
|
10
10
|
<div class="data-extraction-text">
|
|
11
11
|
<p class="title">
|
|
12
|
-
{{ $t("
|
|
12
|
+
<span v-if="redirectingUser"> {{ $t("wait_title") }}</span>
|
|
13
|
+
<span v-else>
|
|
14
|
+
{{ $t("data_being_extracted") }}
|
|
15
|
+
</span>
|
|
13
16
|
</p>
|
|
14
17
|
<div class="description">
|
|
15
|
-
<
|
|
16
|
-
|
|
18
|
+
<span v-if="redirectingUser">
|
|
19
|
+
<p>{{ $t("redirecting_to_documents_list") }}</p>
|
|
20
|
+
</span>
|
|
21
|
+
<span v-else>
|
|
22
|
+
<p>{{ $t("analysing_document") }}</p>
|
|
23
|
+
<p>{{ $t("few_minutes") }}</p>
|
|
24
|
+
</span>
|
|
17
25
|
</div>
|
|
18
26
|
</div>
|
|
19
27
|
</div>
|
|
20
28
|
</template>
|
|
21
29
|
<script>
|
|
30
|
+
import { mapState } from "vuex";
|
|
22
31
|
import AnnotationActionButtons from "./AnnotationActionButtons";
|
|
23
32
|
|
|
24
33
|
export default {
|
|
25
34
|
name: "ExtractingData",
|
|
26
35
|
components: { AnnotationActionButtons },
|
|
36
|
+
computed: {
|
|
37
|
+
...mapState("edit", ["redirectingUser"]),
|
|
38
|
+
},
|
|
27
39
|
};
|
|
28
40
|
</script>
|
|
29
41
|
<style scoped lang="scss" src="../../assets/scss/extracting_data.scss"></style>
|
|
@@ -390,11 +390,15 @@ export default {
|
|
|
390
390
|
});
|
|
391
391
|
});
|
|
392
392
|
|
|
393
|
-
navigateToDocumentsList(
|
|
393
|
+
const redirection = navigateToDocumentsList(
|
|
394
394
|
this.documentsListPath,
|
|
395
395
|
this.projectId,
|
|
396
396
|
this.currentUser.id
|
|
397
397
|
);
|
|
398
|
+
|
|
399
|
+
if (redirection) {
|
|
400
|
+
this.$store.dispatch("edit/setRedirectingUser", true);
|
|
401
|
+
}
|
|
398
402
|
} else {
|
|
399
403
|
// Check if only the category and/or name changes:
|
|
400
404
|
const newCategory = this.updatedDocument[0].category;
|
|
@@ -26,6 +26,26 @@
|
|
|
26
26
|
v-if="!editMode && !publicView && !isDocumentReviewed"
|
|
27
27
|
class="toolbar-divider"
|
|
28
28
|
/>
|
|
29
|
+
|
|
30
|
+
<div v-if="!publicView" class="download-file icons">
|
|
31
|
+
<b-dropdown aria-role="list" position="is-top-right">
|
|
32
|
+
<template #trigger>
|
|
33
|
+
<b-icon icon="download" size="small" class="download-file" />
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<b-dropdown-item aria-role="listitem" @click="handleDownloadFile()">{{
|
|
37
|
+
$t("original_file")
|
|
38
|
+
}}</b-dropdown-item>
|
|
39
|
+
<b-dropdown-item
|
|
40
|
+
aria-role="listitem"
|
|
41
|
+
@click="handleDownloadFile('ocr')"
|
|
42
|
+
>{{ $t("pdf_file") }}</b-dropdown-item
|
|
43
|
+
>
|
|
44
|
+
</b-dropdown>
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<div v-if="!publicView" class="toolbar-divider" />
|
|
48
|
+
|
|
29
49
|
<div class="icons icons-right">
|
|
30
50
|
<div
|
|
31
51
|
:class="[
|
|
@@ -63,6 +83,7 @@ import FitZoomIcon from "../../assets/images/FitZoomIcon";
|
|
|
63
83
|
import PlusIcon from "../../assets/images/PlusIcon";
|
|
64
84
|
import MinusIcon from "../../assets/images/MinusIcon";
|
|
65
85
|
import EditDocIcon from "../../assets/images/EditDocIcon";
|
|
86
|
+
import api from "../../api";
|
|
66
87
|
|
|
67
88
|
export default {
|
|
68
89
|
name: "DocumentToolbar",
|
|
@@ -158,6 +179,41 @@ export default {
|
|
|
158
179
|
this.$store.dispatch("display/updateScale", { scale });
|
|
159
180
|
});
|
|
160
181
|
},
|
|
182
|
+
handleDownloadFile(fileType) {
|
|
183
|
+
let fileUrl;
|
|
184
|
+
// get the file name without the extension
|
|
185
|
+
let fileName = this.getFileName(this.selectedDocument.data_file_name);
|
|
186
|
+
|
|
187
|
+
if (fileType === "ocr") {
|
|
188
|
+
fileUrl = this.selectedDocument.file_url;
|
|
189
|
+
fileName = `${fileName}_${fileType}`;
|
|
190
|
+
} else {
|
|
191
|
+
fileUrl = `/doc/show-original/${this.selectedDocument.id}/`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Automatically download original or ocr files
|
|
195
|
+
return api
|
|
196
|
+
.makeFileRequest(fileUrl)
|
|
197
|
+
.then((myBlob) => {
|
|
198
|
+
const url = URL.createObjectURL(myBlob);
|
|
199
|
+
const link = document.createElement("a");
|
|
200
|
+
link.href = url;
|
|
201
|
+
link.setAttribute("download", fileName);
|
|
202
|
+
link.click();
|
|
203
|
+
URL.revokeObjectURL(link.href);
|
|
204
|
+
})
|
|
205
|
+
.catch((error) => {
|
|
206
|
+
this.$store.dispatch("document/createErrorMessage", {
|
|
207
|
+
error,
|
|
208
|
+
serverErrorMessage: this.$t("server_error"),
|
|
209
|
+
defaultErrorMessage: this.$t("error_downloading_file"),
|
|
210
|
+
});
|
|
211
|
+
console.log(error);
|
|
212
|
+
});
|
|
213
|
+
},
|
|
214
|
+
getFileName(fileName) {
|
|
215
|
+
return fileName.split(".").slice(0, -1).join(".");
|
|
216
|
+
},
|
|
161
217
|
cancelAnnotationEditMode() {
|
|
162
218
|
this.$store.dispatch("document/resetEditAnnotation");
|
|
163
219
|
this.$store.dispatch("selection/disableSelection");
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import DocumentThumbnails from "./DocumentThumbnails.vue";
|
|
2
|
+
|
|
3
|
+
describe("Document Thumbnails", () => {
|
|
4
|
+
beforeEach(() => {
|
|
5
|
+
cy.fetchDocument();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it("shows thumbnails for all document pages", () => {
|
|
9
|
+
cy.mount(DocumentThumbnails);
|
|
10
|
+
cy.get("#document-pages")
|
|
11
|
+
.find(".document-thumbnail")
|
|
12
|
+
.then((elements) => {
|
|
13
|
+
cy.storeState("document", "selectedDocument")
|
|
14
|
+
.its("pages")
|
|
15
|
+
.its("length")
|
|
16
|
+
.should("equal", elements.length);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("loads thumbnail pictures that are shown on screen", () => {
|
|
21
|
+
cy.intercept("GET", "**/page/show-thumbnail/**").as("getThumbnail");
|
|
22
|
+
cy.mount(DocumentThumbnails);
|
|
23
|
+
|
|
24
|
+
cy.get("#document-pages")
|
|
25
|
+
.find(".document-thumbnail")
|
|
26
|
+
.then((elements) => {
|
|
27
|
+
cy.get("@getThumbnail.all")
|
|
28
|
+
.its("length")
|
|
29
|
+
.should("equal", elements.length);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("displays page number correctly", () => {
|
|
34
|
+
cy.mount(DocumentThumbnails);
|
|
35
|
+
cy.get("#document-pages")
|
|
36
|
+
.find(".document-thumbnail")
|
|
37
|
+
.each(($row, index) => {
|
|
38
|
+
cy.wrap($row)
|
|
39
|
+
.find(".number-thumbnail")
|
|
40
|
+
.contains(index + 1);
|
|
41
|
+
cy.wait(1000);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it("navigates to every document thumbnail", () => {
|
|
46
|
+
cy.mount(DocumentThumbnails);
|
|
47
|
+
cy.get("#document-pages")
|
|
48
|
+
.find(".document-thumbnail")
|
|
49
|
+
.each(($row, index) => {
|
|
50
|
+
cy.wrap($row).click();
|
|
51
|
+
cy.storeState("display", "currentPage").should("equal", index + 1);
|
|
52
|
+
cy.wait(1000);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("show loading when a document is not set", () => {
|
|
57
|
+
cy.mount(DocumentThumbnails);
|
|
58
|
+
cy.dispatchAction("document", "setSelectedDocument", null);
|
|
59
|
+
cy.get("#document-pages")
|
|
60
|
+
.find(".document-thumbnail-loading")
|
|
61
|
+
.its("length")
|
|
62
|
+
.should("equal", 1);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div id="document-pages" ref="documentThumbnails">
|
|
3
3
|
<div v-if="selectedDocument">
|
|
4
4
|
<div
|
|
5
5
|
v-for="page in selectedDocument.pages"
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
</div>
|
|
33
33
|
</div>
|
|
34
34
|
</div>
|
|
35
|
-
<div v-else>
|
|
35
|
+
<div v-else class="document-thumbnail-loading">
|
|
36
36
|
<div class="document-thumbnail">
|
|
37
37
|
<div class="image-section">
|
|
38
38
|
<div class="image-container">
|
package/src/icons.js
CHANGED
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
faRepeat,
|
|
18
18
|
faArrowLeft,
|
|
19
19
|
faArrowRight,
|
|
20
|
+
faDownload,
|
|
20
21
|
} from "@fortawesome/free-solid-svg-icons";
|
|
21
22
|
import { FontAwesomeIcon as Icons } from "@fortawesome/vue-fontawesome";
|
|
22
23
|
|
|
@@ -37,7 +38,8 @@ library.add(
|
|
|
37
38
|
faScissors,
|
|
38
39
|
faRepeat,
|
|
39
40
|
faArrowLeft,
|
|
40
|
-
faArrowRight
|
|
41
|
+
faArrowRight,
|
|
42
|
+
faDownload
|
|
41
43
|
);
|
|
42
44
|
|
|
43
45
|
export default Icons;
|
package/src/locales/de.json
CHANGED
|
@@ -132,5 +132,13 @@
|
|
|
132
132
|
"delete_label": "Label löschen",
|
|
133
133
|
"table": "Tabelle",
|
|
134
134
|
"prepare_document": "Dokument vorbereiten",
|
|
135
|
-
"delete_table": "Tabelle löschen"
|
|
135
|
+
"delete_table": "Tabelle löschen",
|
|
136
|
+
"error_downloading_file": "Die Datei konnte nicht heruntergeladen werden.",
|
|
137
|
+
"original_file": "Originaldatei",
|
|
138
|
+
"pdf_file": "PDF Datei",
|
|
139
|
+
"no_labels_in_set": "Dieser Annotationssatz hat keine Beschriftungen.",
|
|
140
|
+
"link_to_add_labels": "Sehen Sie <a href='https://help.konfuzio.com/modules/labels/index.html#add-a-label' target='_blank'>hier</a>, wie Sie sie hinzufügen.",
|
|
141
|
+
"no_annotations_in_annotation_set": "Dieser Annotationssatz enthält keine extrahierten Annotationen für die jeweiligen Beschriftungen.",
|
|
142
|
+
"wait_title": "Bitte warten...",
|
|
143
|
+
"redirecting_to_documents_list": "Wir führen Sie zur Dokumentenliste, sodass Sie Ihre Dokumente weiter überprüfen können, während wir die vorgenommenen Änderungen verarbeiten."
|
|
136
144
|
}
|
package/src/locales/en.json
CHANGED
|
@@ -132,5 +132,13 @@
|
|
|
132
132
|
"edit_label": "Edit label",
|
|
133
133
|
"delete_label": "Delete label",
|
|
134
134
|
"table": "Table",
|
|
135
|
-
"delete_table": "Delete table"
|
|
135
|
+
"delete_table": "Delete table",
|
|
136
|
+
"error_downloading_file": "The file could not be downloaded.",
|
|
137
|
+
"original_file": "Original file",
|
|
138
|
+
"pdf_file": "PDF file",
|
|
139
|
+
"no_labels_in_set": "This annotation set has no labels.",
|
|
140
|
+
"link_to_add_labels": "See how to add them <a href='https://help.konfuzio.com/modules/labels/index.html#add-a-label' target='_blank'>here</a>.",
|
|
141
|
+
"no_annotations_in_annotation_set": "This annotation set has no annotations extracted for its respective labels.",
|
|
142
|
+
"wait_title": "Please wait...",
|
|
143
|
+
"redirecting_to_documents_list": "We are taking you to the documents list, so you can continue reviewing your documents while we process the changes made."
|
|
136
144
|
}
|
package/src/locales/es.json
CHANGED
|
@@ -132,5 +132,13 @@
|
|
|
132
132
|
"new_multi_ann_description": "Seleccione un modelo de datos de los existentes, luego deseleccione las etiquetas que no existen en este documento.",
|
|
133
133
|
"new_multi_ann_title": "Crear múltiples anotaciones",
|
|
134
134
|
"prepare_document": "Prepare el documento",
|
|
135
|
-
"delete_table": "Eliminar tabla"
|
|
135
|
+
"delete_table": "Eliminar tabla",
|
|
136
|
+
"error_downloading_file": "El documento no pudo ser descargado.",
|
|
137
|
+
"original_file": "Documento original",
|
|
138
|
+
"pdf_file": "Documento PDF",
|
|
139
|
+
"no_labels_in_set": "Este grupo de anotaciones no tiene etiquetas.",
|
|
140
|
+
"link_to_add_labels": "Para ver cómo agregarlas haga clic <a href='https://help.konfuzio.com/modules/labels/index.html#add-a-label' target='_blank'>aquí</a>.",
|
|
141
|
+
"no_annotations_in_annotation_set": "Este grupo de anotaciones no tiene anotaciones encontradas para sus respectivas etiquetas.",
|
|
142
|
+
"wait_title": "Por favor espere...",
|
|
143
|
+
"redirecting_to_documents_list": "Lo estamos redirigiendo a la lista de documentos, para que pueda continuar la revisión de sus documentos mientras procesamos los cambios realizados."
|
|
136
144
|
}
|
package/src/store/document.js
CHANGED
|
@@ -17,7 +17,7 @@ const state = {
|
|
|
17
17
|
annotationSets: null,
|
|
18
18
|
annotations: null,
|
|
19
19
|
labels: [],
|
|
20
|
-
documentId:
|
|
20
|
+
documentId: process.env.VUE_APP_DOCUMENT_ID,
|
|
21
21
|
sidebarAnnotationSelected: null,
|
|
22
22
|
documentAnnotationSelected: null,
|
|
23
23
|
selectedDocument: null,
|
|
@@ -1256,7 +1256,9 @@ const mutations = {
|
|
|
1256
1256
|
state.selectedDocument = document;
|
|
1257
1257
|
|
|
1258
1258
|
// this is to handle cache when a document is edited or changed
|
|
1259
|
-
state.selectedDocument
|
|
1259
|
+
if (state.selectedDocument) {
|
|
1260
|
+
state.selectedDocument.downloaded_at = Date.now();
|
|
1261
|
+
}
|
|
1260
1262
|
},
|
|
1261
1263
|
SET_RECALCULATING_ANNOTATIONS: (state, recalculatingAnnotations) => {
|
|
1262
1264
|
state.recalculatingAnnotations = recalculatingAnnotations;
|
package/src/store/edit.js
CHANGED
|
@@ -16,6 +16,7 @@ const state = {
|
|
|
16
16
|
updatedDocument: [],
|
|
17
17
|
showEditConfirmationModal: false,
|
|
18
18
|
submitEditChanges: false,
|
|
19
|
+
redirectingUser: false,
|
|
19
20
|
};
|
|
20
21
|
|
|
21
22
|
const getters = {
|
|
@@ -260,6 +261,10 @@ const actions = {
|
|
|
260
261
|
setShowEditConfirmationModal: ({ commit }, value) => {
|
|
261
262
|
commit("SET_SHOW_EDIT_CONFIRMATION_MODAL", value);
|
|
262
263
|
},
|
|
264
|
+
|
|
265
|
+
setRedirectingUser: ({ commit }, value) => {
|
|
266
|
+
commit("SET_REDIRECTING_USER", value);
|
|
267
|
+
},
|
|
263
268
|
};
|
|
264
269
|
|
|
265
270
|
const mutations = {
|
|
@@ -290,6 +295,9 @@ const mutations = {
|
|
|
290
295
|
SET_SUBMIT_EDIT_CHANGES: (state, value) => {
|
|
291
296
|
state.submitEditChanges = value;
|
|
292
297
|
},
|
|
298
|
+
SET_REDIRECTING_USER: (state, value) => {
|
|
299
|
+
state.redirectingUser = value;
|
|
300
|
+
},
|
|
293
301
|
};
|
|
294
302
|
|
|
295
303
|
export default {
|
package/src/store/project.js
CHANGED
package/src/utils/utils.js
CHANGED