@konfuzio/document-validation-ui 0.1.5-styles-refactor → 0.1.6-pre-release-1

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 (49) 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/package.json +1 -1
  6. package/src/.DS_Store +0 -0
  7. package/src/assets/images/MagicWandIcon.vue +16 -0
  8. package/src/assets/images/NotFoundIcon.vue +16 -0
  9. package/src/assets/images/SplitZigZag.vue +47 -14
  10. package/src/assets/images/StarIcon.vue +16 -0
  11. package/src/assets/scss/document_annotations.scss +9 -59
  12. package/src/assets/scss/document_category.scss +0 -1
  13. package/src/assets/scss/document_dashboard.scss +6 -0
  14. package/src/assets/scss/document_edit.scss +90 -46
  15. package/src/assets/scss/main.scss +67 -44
  16. package/src/assets/scss/splitting_confirmation_modal.scss +41 -0
  17. package/src/components/DocumentAnnotations/AnnotationActionButtons.vue +153 -0
  18. package/src/components/DocumentAnnotations/AnnotationDetails.vue +21 -4
  19. package/src/components/DocumentAnnotations/AnnotationRow.vue +97 -34
  20. package/src/components/DocumentAnnotations/AnnotationSetActionButtons.vue +86 -0
  21. package/src/components/DocumentAnnotations/CategorizeModal.vue +24 -2
  22. package/src/components/DocumentAnnotations/DocumentAnnotations.vue +77 -81
  23. package/src/components/DocumentAnnotations/EmptyAnnotation.vue +16 -3
  24. package/src/components/DocumentAnnotations/ExtractingData.vue +3 -3
  25. package/src/components/DocumentAnnotations/index.js +0 -1
  26. package/src/components/DocumentCategory.vue +13 -5
  27. package/src/components/DocumentDashboard.vue +17 -6
  28. package/src/components/DocumentEdit/DocumentEdit.vue +208 -68
  29. package/src/components/DocumentEdit/EditConfirmationModal.vue +54 -0
  30. package/src/components/DocumentEdit/EditPages.vue +29 -18
  31. package/src/components/DocumentEdit/EditSidebar.vue +92 -45
  32. package/src/components/DocumentEdit/SidebarButtons.vue +53 -0
  33. package/src/components/DocumentEdit/SplitInfoBar.vue +19 -0
  34. package/src/components/DocumentEdit/SplitOverview.vue +4 -5
  35. package/src/components/{DocumentError.vue → DocumentModals/DocumentErrorModal.vue} +3 -4
  36. package/src/components/{NotOptimizedViewportModal.vue → DocumentModals/NotOptimizedViewportModal.vue} +2 -2
  37. package/src/components/DocumentModals/SplittingSuggestionsModal.vue +120 -0
  38. package/src/components/DocumentPage/ActionBar.vue +3 -3
  39. package/src/components/DocumentPage/ScrollingDocument.vue +7 -3
  40. package/src/components/DocumentTopBar/DocumentTopBarButtons.vue +35 -30
  41. package/src/components/DocumentTopBar/KeyboardActionsDescription.vue +3 -1
  42. package/src/locales/de.json +19 -6
  43. package/src/locales/en.json +20 -6
  44. package/src/locales/es.json +19 -6
  45. package/src/store/document.js +81 -17
  46. package/src/store/edit.js +67 -48
  47. package/src/store/project.js +14 -14
  48. package/src/components/DocumentAnnotations/ActionButtons.vue +0 -257
  49. package/src/components/DocumentAnnotations/RejectedLabels.vue +0 -96
@@ -14,17 +14,13 @@
14
14
 
15
15
  <!-- When there's no annotations in the label -->
16
16
  <div v-else-if="annotationSets.length === 0">
17
- <CategorizeModal v-if="!publicView" />
17
+ <CategorizeModal
18
+ v-if="!publicView && !waitingForSplittingConfirmation(selectedDocument)"
19
+ />
18
20
  <EmptyState />
19
21
  </div>
20
22
 
21
- <div
22
- v-else
23
- :class="[
24
- 'annotation-set-list',
25
- missingAnnotations.length && !publicView && 'showing-rejected',
26
- ]"
27
- >
23
+ <div v-else :class="['annotation-set-list']">
28
24
  <CategorizeModal v-if="!publicView" />
29
25
  <div
30
26
  v-for="(annotationSet, indexGroup) in annotationSets"
@@ -40,18 +36,25 @@
40
36
  }}
41
37
  </div>
42
38
  <div class="labelset-action-buttons">
43
- <ActionButtons
44
- :reject-all-empty-btn="true"
45
- :annotation-set="annotationSet"
46
- :accept-all-btn="true"
47
- @reject-all-empty="
48
- rejectMissingAnnotations(null, null, annotationSet, true)
39
+ <AnnotationSetActionButtons
40
+ :number-of-empty-labels-in-annotation-set="
41
+ emptyLabelsLength(annotationSet)
42
+ "
43
+ :number-of-pending-annotations-in-annotation-set="
44
+ annotationsWithPendingReviewLength(annotationSet)
45
+ "
46
+ @mark-all-empty-missing="
47
+ markAnnotationsAsMissing(null, null, annotationSet, true)
49
48
  "
50
- @hover-annotation-set-to-reject="
51
- handleHoverAnnotationSet(annotationSet, 'reject')
49
+ @hover-annotation-set-to-mark-missing="
50
+ handleHoverAnnotationSet(annotationSet, 'missing')
51
+ "
52
+ @leave-annotation-set-to-mark-missing="
53
+ handleHoverAnnotationSet(null)
54
+ "
55
+ @accept-all-pending-annotations="
56
+ acceptPendingAnnotationsInAnnotationSet(annotationSet)
52
57
  "
53
- @leave-annotation-set-to-reject="handleHoverAnnotationSet(null)"
54
- @accept-group="acceptGroup(annotationSet)"
55
58
  @hover-annotation-set-to-accept="
56
59
  handleHoverAnnotationSet(annotationSet, 'accept')
57
60
  "
@@ -61,33 +64,25 @@
61
64
  </div>
62
65
 
63
66
  <div v-for="label in annotationSet.labels" :key="label.id">
64
- <div v-if="labelNotRejected(annotationSet, label)" class="labels">
67
+ <div class="labels">
65
68
  <DocumentLabel
66
69
  :label="label"
67
70
  :annotation-set="annotationSet"
68
71
  :index-group="indexGroup"
69
- @handle-reject="rejectMissingAnnotations"
72
+ @handle-missing-annotation="markAnnotationsAsMissing"
70
73
  />
71
74
  </div>
72
75
  </div>
73
76
  </div>
74
77
  </div>
75
-
76
- <div
77
- v-if="!publicView && missingAnnotations.length"
78
- class="rejected-labels-list"
79
- >
80
- <RejectedLabels :missing-annotations="missingAnnotations" />
81
- </div>
82
78
  </div>
83
79
  </template>
84
80
  <script>
85
81
  import { mapGetters, mapState } from "vuex";
86
82
  import EmptyState from "./EmptyState";
87
83
  import ExtractingData from "./ExtractingData";
88
- import ActionButtons from "./ActionButtons";
84
+ import AnnotationSetActionButtons from "./AnnotationSetActionButtons";
89
85
  import DocumentLabel from "./DocumentLabel";
90
- import RejectedLabels from "./RejectedLabels";
91
86
  import LoadingAnnotations from "./LoadingAnnotations";
92
87
  import CategorizeModal from "./CategorizeModal";
93
88
 
@@ -98,9 +93,8 @@ export default {
98
93
  components: {
99
94
  EmptyState,
100
95
  ExtractingData,
101
- ActionButtons,
96
+ AnnotationSetActionButtons,
102
97
  DocumentLabel,
103
- RejectedLabels,
104
98
  LoadingAnnotations,
105
99
  CategorizeModal,
106
100
  },
@@ -123,9 +117,15 @@ export default {
123
117
  "loading",
124
118
  "labels",
125
119
  "selectedDocument",
120
+ "splittingSuggestions",
126
121
  ]),
127
122
  ...mapGetters("category", ["category"]),
128
- ...mapGetters("document", ["numberOfAnnotationSetGroup"]),
123
+ ...mapGetters("document", [
124
+ "numberOfAnnotationSetGroup",
125
+ "emptyLabelsLength",
126
+ "annotationsWithPendingReviewLength",
127
+ "waitingForSplittingConfirmation",
128
+ ]),
129
129
  isAnnotationBeingEdited() {
130
130
  return this.editAnnotation && this.editAnnotation.id;
131
131
  },
@@ -263,6 +263,18 @@ export default {
263
263
  this.count = currentAnnIndex + 1;
264
264
  }
265
265
 
266
+ // Skip missing annotations
267
+ if (this.focusedAnnotationIsMarkedAsMissing(annotations, this.count)) {
268
+ for (let i = this.count; i < annotations.length; i++) {
269
+ if (!this.focusedAnnotationIsMarkedAsMissing(annotations, i)) {
270
+ break;
271
+ }
272
+ this.count++;
273
+ }
274
+ }
275
+
276
+ if (!annotations[this.count]) return;
277
+
266
278
  annotations[this.count].click();
267
279
 
268
280
  // scroll to current annotation if not empty
@@ -285,6 +297,18 @@ export default {
285
297
  this.count = currentAnnIndex - 1;
286
298
  }
287
299
 
300
+ // Skip missing annotations
301
+ if (this.focusedAnnotationIsMarkedAsMissing(annotations, this.count)) {
302
+ for (let i = this.count; i < annotations.length; i--) {
303
+ if (!this.focusedAnnotationIsMarkedAsMissing(annotations, i)) {
304
+ break;
305
+ }
306
+ this.count--;
307
+ }
308
+ }
309
+
310
+ if (!annotations[this.count]) return;
311
+
288
312
  annotations[this.count].click();
289
313
 
290
314
  // scroll to current annotation if not empty
@@ -311,9 +335,9 @@ export default {
311
335
  annotations[currentAnnIndex].className.includes("label-empty") &&
312
336
  annotations[currentAnnIndex].className.includes("clicked")
313
337
  ) {
314
- // Reject annotation
338
+ // Mark annotation as missing
315
339
  if (this.editAnnotation.id === annotations[currentAnnIndex].id) {
316
- this.rejectMissingAnnotations();
340
+ this.markAnnotationsAsMissing();
317
341
  }
318
342
  this.jumpToNextAnnotation = true;
319
343
  } else {
@@ -322,45 +346,17 @@ export default {
322
346
  }
323
347
  },
324
348
 
325
- labelNotRejected(annotationSet, label) {
326
- // Check if the combined label and label set have been rejected
327
- // or if the document is in public mode
328
- if (
329
- this.missingAnnotations.length === 0 ||
330
- !this.showMissingAnnotations()
331
- ) {
332
- return true;
333
- } else {
334
- let found;
335
-
336
- if (annotationSet && annotationSet.id) {
337
- found = this.missingAnnotations.filter(
338
- (el) =>
339
- el.label === label.id && el.annotation_set === annotationSet.id
340
- );
341
- } else {
342
- found = this.missingAnnotations.filter(
343
- (el) =>
344
- el.label === label.id &&
345
- el.label_set === annotationSet.label_set.id
346
- );
347
- }
348
-
349
- if (found.length !== 0) {
350
- return false;
351
- } else {
352
- return true;
353
- }
354
- }
349
+ focusedAnnotationIsMarkedAsMissing(annotations, index) {
350
+ return annotations[index].classList.value.includes("missing-annotation");
355
351
  },
356
352
 
357
- rejectMissingAnnotations(label, labelSet, annotationSet, rejectAll) {
358
- let rejected;
353
+ markAnnotationsAsMissing(label, labelSet, annotationSet, markAllMissing) {
354
+ let missing;
359
355
 
360
- if (label && labelSet && !rejectAll) {
361
- // if single rejection is triggered by clicking the button
356
+ if (label && labelSet && !markAllMissing) {
357
+ // if annotation is marked as missing by clicking the button
362
358
 
363
- rejected = [
359
+ missing = [
364
360
  {
365
361
  document: parseInt(this.documentId),
366
362
  label: label,
@@ -369,24 +365,24 @@ export default {
369
365
  },
370
366
  ];
371
367
  } else if (this.editAnnotation && this.editAnnotation.id !== null) {
372
- // if single rejection is triggered from "delete" key
368
+ // iif annotation is marked as missing from "delete" key
373
369
 
374
- rejected = {
370
+ missing = {
375
371
  document: parseInt(this.documentId),
376
372
  label: this.editAnnotation.label,
377
373
  label_set: this.editAnnotation.labelSet,
378
374
  annotation_set: this.editAnnotation.annotationSet,
379
375
  };
380
- } else if (annotationSet && rejectAll) {
381
- // reject all labels in annotation set
376
+ } else if (annotationSet && markAllMissing) {
377
+ // mark all annotations as missing in annotation set
382
378
 
383
379
  const allEmptyLabels = annotationSet.labels.filter(
384
380
  (label) => label.annotations.length === 0
385
381
  );
386
382
 
387
- // Check if any of the empty annotations was already rejected individually
383
+ // Check if any of the empty annotations was already marked as missing individually
388
384
  // and remove them
389
- const toReject = [];
385
+ const toMarkAsMissing = [];
390
386
 
391
387
  allEmptyLabels.map((label) => {
392
388
  const found = this.missingAnnotations.find(
@@ -397,11 +393,11 @@ export default {
397
393
  );
398
394
 
399
395
  if (!found) {
400
- toReject.push(label);
396
+ toMarkAsMissing.push(label);
401
397
  }
402
398
  });
403
399
 
404
- rejected = toReject.map((label) => {
400
+ missing = toMarkAsMissing.map((label) => {
405
401
  return {
406
402
  document: parseInt(this.documentId),
407
403
  label: label.id,
@@ -411,10 +407,10 @@ export default {
411
407
  });
412
408
  }
413
409
 
414
- this.$store.dispatch("document/setRejectedMissingAnnotations", rejected);
410
+ this.$store.dispatch("document/setAnnotationsMarkedAsMissing", missing);
415
411
 
416
412
  this.$store
417
- .dispatch("document/addMissingAnnotations", rejected)
413
+ .dispatch("document/addMissingAnnotations", missing)
418
414
  .then((response) => {
419
415
  if (response) {
420
416
  this.jumpToNextAnnotation = true;
@@ -430,7 +426,7 @@ export default {
430
426
  });
431
427
  })
432
428
  .finally(() => {
433
- this.$store.dispatch("document/setRejectedMissingAnnotations", null);
429
+ this.$store.dispatch("document/setAnnotationsMarkedAsMissing", null);
434
430
  });
435
431
  },
436
432
 
@@ -449,7 +445,7 @@ export default {
449
445
  this.$store.dispatch("document/setHoveredAnnotationSet", hovered);
450
446
  },
451
447
 
452
- acceptGroup(annotationSet) {
448
+ acceptPendingAnnotationsInAnnotationSet(annotationSet) {
453
449
  const annotationsToAccept = [];
454
450
 
455
451
  annotationSet.labels.map((label) => {
@@ -12,6 +12,7 @@
12
12
  'error-editing',
13
13
  isEmptyAnnotationEditable() ? '' : 'label-empty',
14
14
  isAnnotationBeingEdited() && 'clicked',
15
+ annotationIsNotFound(annotationSet, label) && 'missing-annotation',
15
16
  ]"
16
17
  :contenteditable="isEmptyAnnotationEditable()"
17
18
  @keypress.enter="saveEmptyAnnotationChanges"
@@ -21,6 +22,12 @@
21
22
  <span v-if="span && span.offset_string && isEmptyAnnotationEditable()">
22
23
  {{ span.offset_string }}
23
24
  </span>
25
+ <span
26
+ v-else-if="annotationIsNotFound(annotationSet, label)"
27
+ class="not-found-text"
28
+ >
29
+ {{ $t("missing_from_document") }}
30
+ </span>
24
31
  <span v-else>
25
32
  {{ $t("no_data_found") }}
26
33
  </span>
@@ -68,6 +75,7 @@ export default {
68
75
  ...mapGetters("document", [
69
76
  "isAnnotationInEditMode",
70
77
  "getTextFromEntities",
78
+ "annotationIsNotFound",
71
79
  ]),
72
80
  ...mapGetters("selection", ["isValueArray"]),
73
81
  ...mapState("selection", ["spanSelection", "elementSelected"]),
@@ -133,6 +141,7 @@ export default {
133
141
  }
134
142
  },
135
143
  },
144
+
136
145
  methods: {
137
146
  emptyAnnotationId() {
138
147
  if (!this.annotationSet || !this.label) return;
@@ -147,7 +156,11 @@ export default {
147
156
  return this.isAnnotationInEditMode(this.emptyAnnotationId());
148
157
  },
149
158
  handleEditEmptyAnnotation() {
150
- if (this.publicView) return;
159
+ if (
160
+ this.publicView ||
161
+ this.annotationIsNotFound(this.annotationSet, this.label)
162
+ )
163
+ return;
151
164
 
152
165
  if (
153
166
  !this.publicView &&
@@ -190,8 +203,8 @@ export default {
190
203
  this.elementSelected === this.emptyAnnotationId() && !this.isLoading
191
204
  );
192
205
  } else if (
193
- this.spanSelection &&
194
- this.spanSelection[this.spanIndex] === 0
206
+ (this.spanSelection && this.spanSelection[this.spanIndex] === 0) ||
207
+ this.annotationIsNotFound(this.annotationSet, this.label)
195
208
  ) {
196
209
  return false;
197
210
  } else {
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="data-extraction-container">
3
3
  <div class="loading-container">
4
- <ActionButtons
4
+ <AnnotationActionButtons
5
5
  :is-loading="true"
6
6
  :save-btn="false"
7
7
  :cancel-btn="false"
@@ -19,11 +19,11 @@
19
19
  </div>
20
20
  </template>
21
21
  <script>
22
- import ActionButtons from "./ActionButtons";
22
+ import AnnotationActionButtons from "./AnnotationActionButtons";
23
23
 
24
24
  export default {
25
25
  name: "ExtractingData",
26
- components: { ActionButtons }
26
+ components: { AnnotationActionButtons },
27
27
  };
28
28
  </script>
29
29
  <style scoped lang="scss" src="../../assets/scss/extracting_data.scss"></style>
@@ -3,6 +3,5 @@ export { default as AnnotationContent } from "./AnnotationContent";
3
3
  export { default as EmptyAnnotation } from "./EmptyAnnotation";
4
4
  export { default as DocumentLabel } from "./DocumentLabel";
5
5
  export { default as AnnotationDetails } from "./AnnotationDetails";
6
- export { default as RejectedLabels } from "./RejectedLabels";
7
6
  export { default as ChooseLabelSetModal } from "./ChooseLabelSetModal";
8
7
  export { default as AnnotationRow } from "./AnnotationRow";
@@ -29,11 +29,7 @@
29
29
  {{ $t("category") }}
30
30
  </p>
31
31
  <div class="category-name">
32
- {{
33
- !splitMode
34
- ? categoryName(selectedDocument.category)
35
- : categoryName(updatedDocument[index].category)
36
- }}
32
+ {{ setCategoryDefaultText }}
37
33
  </div>
38
34
  </div>
39
35
  <div :class="[!splitMode && 'caret-section']">
@@ -102,6 +98,18 @@ export default {
102
98
  ...mapState("document", ["selectedDocument", "annotations"]),
103
99
  ...mapState("category", ["categories"]),
104
100
  ...mapState("edit", ["editMode", "updatedDocument"]),
101
+
102
+ setCategoryDefaultText() {
103
+ if (!this.splitMode) {
104
+ return this.categoryName(this.selectedDocument.category);
105
+ } else {
106
+ const categoryName = this.categoryName(
107
+ this.updatedDocument[this.index].category
108
+ );
109
+
110
+ return categoryName ? categoryName : this.$t("choose_category");
111
+ }
112
+ },
105
113
  },
106
114
  watch: {
107
115
  categories(newValue) {
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="dashboard">
3
3
  <DocumentTopBar />
4
- <div :class="['dashboard-viewer', editMode ? 'edit-mode' : '']">
4
+ <div :class="['dashboard-viewer', splitOverview ? 'edit-mode' : '']">
5
5
  <DocumentThumbnails v-if="!editMode" ref="documentPages" />
6
6
  <ScrollingDocument ref="scrollingDocument" class="dashboard-document" />
7
7
  <DocumentAnnotations v-if="!editMode" ref="annotations" />
@@ -18,7 +18,7 @@
18
18
  </transition>
19
19
  </div>
20
20
  <div v-if="showDocumentError" class="error-modal">
21
- <DocumentError />
21
+ <DocumentErrorModal />
22
22
  </div>
23
23
  <div v-if="!optimalResolution" class="not-optimized">
24
24
  <NotOptimizedViewportModal />
@@ -28,6 +28,13 @@
28
28
  {{ $t("resolution_not_supported") }}
29
29
  </div>
30
30
  </div>
31
+ <div
32
+ v-if="
33
+ selectedDocument && waitingForSplittingConfirmation(selectedDocument)
34
+ "
35
+ >
36
+ <SplittingSuggestionsModal />
37
+ </div>
31
38
  </div>
32
39
  </template>
33
40
 
@@ -39,8 +46,9 @@ import { DocumentThumbnails } from "./DocumentThumbnails";
39
46
  import { DocumentAnnotations } from "./DocumentAnnotations";
40
47
  import { DocumentEdit } from "./DocumentEdit";
41
48
  import ErrorMessage from "./ErrorMessage";
42
- import NotOptimizedViewportModal from "./NotOptimizedViewportModal";
43
- import DocumentError from "./DocumentError";
49
+ import NotOptimizedViewportModal from "../components/DocumentModals/NotOptimizedViewportModal";
50
+ import DocumentErrorModal from "../components/DocumentModals/DocumentErrorModal";
51
+ import SplittingSuggestionsModal from "../components/DocumentModals/SplittingSuggestionsModal";
44
52
 
45
53
  /**
46
54
  * This component shows the PDF pages in a scrolling component and
@@ -56,7 +64,8 @@ export default {
56
64
  DocumentEdit,
57
65
  ErrorMessage,
58
66
  NotOptimizedViewportModal,
59
- DocumentError,
67
+ DocumentErrorModal,
68
+ SplittingSuggestionsModal,
60
69
  },
61
70
  data() {
62
71
  return {
@@ -77,9 +86,11 @@ export default {
77
86
  "showDocumentError",
78
87
  "errorMessageWidth",
79
88
  "selectedDocument",
89
+ "splittingSuggestions",
80
90
  ]),
81
- ...mapState("edit", ["editMode"]),
91
+ ...mapState("edit", ["editMode", "splitOverview"]),
82
92
  ...mapGetters("display", ["isMinimumWidth"]),
93
+ ...mapGetters("document", ["waitingForSplittingConfirmation"]),
83
94
  },
84
95
  watch: {
85
96
  selectedDocument(newDocument, oldDocument) {