@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.
Files changed (34) hide show
  1. package/dist/css/app.css +1 -1
  2. package/dist/index.html +1 -1
  3. package/dist/js/app.js +1 -1
  4. package/dist/js/app.js.map +1 -1
  5. package/dist/js/chunk-vendors.js +1 -1
  6. package/dist/js/chunk-vendors.js.map +1 -1
  7. package/package.json +1 -1
  8. package/src/.DS_Store +0 -0
  9. package/src/api.js +13 -9
  10. package/src/assets/images/ServerImage.vue +1 -1
  11. package/src/assets/scss/document_annotations.scss +199 -183
  12. package/src/assets/scss/document_thumbnails.scss +1 -1
  13. package/src/assets/scss/document_toolbar.scss +21 -7
  14. package/src/assets/scss/theme.scss +22 -0
  15. package/src/components/App.cy.js +1 -1
  16. package/src/components/App.vue +1 -1
  17. package/src/components/DocumentAnnotations/AnnotationDetails.vue +1 -1
  18. package/src/components/DocumentAnnotations/DocumentAnnotations.vue +37 -12
  19. package/src/components/DocumentAnnotations/DocumentLabel.vue +2 -2
  20. package/src/components/DocumentAnnotations/ExtractingData.vue +15 -3
  21. package/src/components/DocumentEdit/DocumentEdit.vue +5 -1
  22. package/src/components/DocumentModals/DocumentErrorModal.vue +1 -1
  23. package/src/components/DocumentPage/DocumentPage.vue +1 -1
  24. package/src/components/DocumentPage/DocumentToolbar.vue +56 -0
  25. package/src/components/DocumentThumbnails/DocumentThumbnails.cy.js +64 -0
  26. package/src/components/DocumentThumbnails/DocumentThumbnails.vue +2 -2
  27. package/src/icons.js +3 -1
  28. package/src/locales/de.json +9 -1
  29. package/src/locales/en.json +9 -1
  30. package/src/locales/es.json +9 -1
  31. package/src/store/document.js +4 -2
  32. package/src/store/edit.js +8 -0
  33. package/src/store/project.js +1 -1
  34. package/src/utils/utils.js +2 -0
@@ -54,7 +54,10 @@
54
54
  )}`
55
55
  }}
56
56
  </div>
57
- <div class="labelset-action-buttons">
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-for="label in annotationSet.labels" :key="label.id">
86
- <div
87
- v-if="!(label.annotations.length === 0 && publicView)"
88
- class="labels"
89
- >
90
- <DocumentLabel
91
- :label="label"
92
- :annotation-set="annotationSet"
93
- :index-group="indexGroup"
94
- @handle-missing-annotation="markAnnotationsAsMissing"
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 v-if="!publicView" class="label-annotations-pending">
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 v-if="!publicView" class="label-annotations-accepted">
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("data_being_extracted") }}
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
- <p>{{ $t("analysing_document") }}</p>
16
- <p>{{ $t("few_minutes") }}</p>
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;
@@ -3,7 +3,7 @@
3
3
  <b-modal
4
4
  v-model="isModalActive"
5
5
  :width="400"
6
- can-cancel="['x']"
6
+ :can-cancel="['x']"
7
7
  :on-cancel="closeModal"
8
8
  >
9
9
  <section class="modal-card-body">
@@ -459,7 +459,7 @@ export default {
459
459
  return;
460
460
  }
461
461
  api
462
- .makeImageRequest(
462
+ .makeFileRequest(
463
463
  `${this.page.image_url}?${this.selectedDocument.downloaded_at}`
464
464
  )
465
465
  .then((myBlob) => {
@@ -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 ref="documentThumbnails" class="document-pages">
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;
@@ -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
  }
@@ -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
  }
@@ -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
  }
@@ -17,7 +17,7 @@ const state = {
17
17
  annotationSets: null,
18
18
  annotations: null,
19
19
  labels: [],
20
- documentId: null,
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.downloaded_at = Date.now();
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 {
@@ -2,7 +2,7 @@ import myImports from "../api";
2
2
  const HTTP = myImports.HTTP;
3
3
 
4
4
  const state = {
5
- projectId: null,
5
+ projectId: process.env.VUE_APP_PROJECT_ID,
6
6
  currentUser: null,
7
7
  documentsListPath: null,
8
8
  documentsInProject: null,
@@ -45,6 +45,8 @@ export function navigateToDocumentsList(path, projectId, userId) {
45
45
  const newPath = `${path}${slash}${parameters}`;
46
46
 
47
47
  window.location.href = newPath;
48
+
49
+ return true;
48
50
  }
49
51
 
50
52
  export function isElementArray(element) {