@konfuzio/document-validation-ui 0.1.8 → 0.1.9-pre-release-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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konfuzio/document-validation-ui",
3
- "version": "0.1.8",
3
+ "version": "0.1.9-pre-release-2",
4
4
  "repository": "git://github.com:konfuzio-ai/document-validation-ui.git",
5
5
  "main": "dist/app.js",
6
6
  "scripts": {
package/src/.DS_Store ADDED
Binary file
@@ -21,9 +21,6 @@
21
21
  >
22
22
  {{ span.offset_string }}
23
23
  </span>
24
- <span v-else class="annotation-value">
25
- {{ span.offset_string }}
26
- </span>
27
24
  </div>
28
25
  </template>
29
26
 
@@ -70,59 +67,34 @@ export default {
70
67
  ...mapGetters("document", [
71
68
  "isAnnotationInEditMode",
72
69
  "pageAtIndex",
73
- "getTextFromEntities",
74
70
  "isDocumentReviewed",
75
71
  ]),
76
72
  ...mapGetters("display", ["bboxToRect"]),
77
- ...mapGetters("selection", ["isValueArray"]),
78
73
  ...mapState("selection", ["spanSelection"]),
79
74
  ...mapState("document", [
80
75
  "editAnnotation",
81
76
  "publicView",
82
77
  "annotations",
83
78
  "newAcceptedAnnotations",
84
- "selectedEntities",
85
79
  "showActionError",
86
80
  ]),
81
+
82
+ isAnnotationDeleted() {
83
+ return this.annotation.revised && !this.annotation.is_correct;
84
+ },
85
+ isAnnotationBeingEdited() {
86
+ return this.isAnnotationInEditMode(this.annotation.id, this.spanIndex);
87
+ },
87
88
  annotationText() {
88
89
  if (this.isAnnotationBeingEdited) {
89
- if (this.selectedEntities && this.selectedEntities.length > 0) {
90
- return this.getTextFromEntities();
91
- }
92
90
  return this.$refs.contentEditable.textContent.trim();
93
91
  } else {
94
92
  return this.span.offset_string;
95
93
  }
96
94
  },
97
- isAnnotationDeleted() {
98
- return this.annotation.revised && !this.annotation.is_correct;
99
- },
100
- isAnnotationBeingEdited() {
101
- return this.isAnnotationInEditMode(this.annotation.id, this.spanIndex);
102
- },
103
95
  },
96
+
104
97
  watch: {
105
- span(newValue) {
106
- if (this.isAnnotationBeingEdited && newValue) {
107
- if (this.isValueArray(newValue)) {
108
- newValue.map((span) => {
109
- if (
110
- span.offset_string &&
111
- span.offset_string !== this.span.offset_string
112
- )
113
- this.setText(span.offset_string);
114
- });
115
- } else {
116
- if (
117
- (newValue.offset_string &&
118
- newValue.offset_string !== this.span.offset_string) ||
119
- newValue.offset_string !==
120
- this.$refs.contentEditable.textContent.trim()
121
- )
122
- this.setText(newValue.offset_string);
123
- }
124
- }
125
- },
126
98
  editAnnotation(newAnnotation, oldAnnotation) {
127
99
  // verify if new annotation in edit mode is not this one and if this
128
100
  // one was selected before so we set the state to the previous one (like a cancel)
@@ -135,16 +107,7 @@ export default {
135
107
  this.handleCancel(true);
136
108
  }
137
109
  },
138
- selectedEntities(newValue) {
139
- if (!newValue) return;
140
110
 
141
- if (
142
- this.editAnnotation &&
143
- this.annotation.id === this.editAnnotation.id
144
- ) {
145
- this.setText(this.getTextFromEntities());
146
- }
147
- },
148
111
  saveChanges(newValue) {
149
112
  if (newValue) {
150
113
  this.saveAnnotationChanges();
@@ -169,6 +132,7 @@ export default {
169
132
  !this.isLoading
170
133
  ) {
171
134
  this.$store.dispatch("selection/selectElement", this.annotation.id);
135
+
172
136
  this.$store
173
137
  .dispatch("document/setEditAnnotation", {
174
138
  id: this.annotation.id,
@@ -221,7 +185,7 @@ export default {
221
185
  this.$refs.contentEditable.blur();
222
186
  }
223
187
 
224
- this.$store.dispatch("document/setSelectedEntities", null);
188
+ this.$store.dispatch("selection/setSelectedEntities", null);
225
189
  },
226
190
  handlePaste(event) {
227
191
  // TODO: modify to only paste plain text
@@ -234,11 +198,18 @@ export default {
234
198
  event.preventDefault();
235
199
  }
236
200
 
201
+ let index;
202
+ if (this.editAnnotation && this.editAnnotation.index) {
203
+ index = this.editAnnotation.index;
204
+ } else {
205
+ index = this.spanIndex;
206
+ }
207
+
237
208
  // API call handled in parent component - AnnotationRow
238
209
  this.$emit(
239
210
  "save-annotation-changes",
240
211
  this.annotation,
241
- this.spanIndex,
212
+ index,
242
213
  this.span,
243
214
  this.annotationText
244
215
  );
@@ -3,9 +3,10 @@
3
3
  :animated="false"
4
4
  :position="fromTable ? 'is-top' : 'is-bottom'"
5
5
  :class="[!fromTable && 'left-aligned', 'annotation-details']"
6
+ :active="!publicView"
6
7
  >
7
8
  <div :class="['label-icon', fromTable && 'is-small']">
8
- <div v-if="created(annotation) || edited(annotation)">
9
+ <div v-if="(created(annotation) || edited(annotation)) && !publicView">
9
10
  <div
10
11
  v-if="accepted(annotation)"
11
12
  :class="[
@@ -28,13 +29,13 @@
28
29
  </div>
29
30
  </div>
30
31
  <div
31
- v-else-if="annotationIsNotFound(annotationSet, label)"
32
+ v-else-if="annotationIsNotFound(annotationSet, label) && !publicView"
32
33
  :class="['annotation-details-icon', animate ? 'animated-ripple' : '']"
33
34
  >
34
35
  <NotFoundIcon />
35
36
  </div>
36
37
  <div
37
- v-else-if="notExtracted(annotation)"
38
+ v-else-if="notExtracted(annotation) && !publicView"
38
39
  :class="[
39
40
  'annotation-details-icon',
40
41
  animate ? 'animated-ripple' : '',
@@ -45,7 +46,7 @@
45
46
  </div>
46
47
  <div v-else>
47
48
  <div
48
- v-if="accepted(annotation)"
49
+ v-if="accepted(annotation) && !publicView"
49
50
  :class="[
50
51
  'annotation-details-icon success',
51
52
  animate ? 'animated-ripple' : '',
@@ -143,7 +144,7 @@
143
144
  </b-tooltip>
144
145
  </template>
145
146
  <script>
146
- import { mapGetters } from "vuex";
147
+ import { mapGetters, mapState } from "vuex";
147
148
  import CheckMark from "../../assets/images/CheckMark";
148
149
  import AcceptedCheckMark from "../../assets/images/AcceptedCheckMark";
149
150
  import QuestionMark from "../../assets/images/QuestionMark";
@@ -199,6 +200,7 @@ export default {
199
200
  "getUser",
200
201
  "annotationIsNotFound",
201
202
  ]),
203
+ ...mapState("document", ["publicView"]),
202
204
  },
203
205
  watch: {
204
206
  annotation(newAnnotation, oldAnnotation) {
@@ -71,6 +71,9 @@
71
71
  :annotation-set="annotationSet"
72
72
  :is-hovered="hoveredAnnotation"
73
73
  :save-changes="saveChanges"
74
+ :is-missing-annotation="
75
+ annotationIsNotFound(annotationSet, label)
76
+ "
74
77
  @save-empty-annotation-changes="saveEmptyAnnotationChanges"
75
78
  />
76
79
  </div>
@@ -80,6 +83,7 @@
80
83
  :annotation-set="annotationSet"
81
84
  :is-hovered="hoveredAnnotation"
82
85
  :save-changes="saveChanges"
86
+ :is-missing-annotation="annotationIsNotFound(annotationSet, label)"
83
87
  @save-empty-annotation-changes="saveEmptyAnnotationChanges"
84
88
  />
85
89
  </div>
@@ -110,6 +114,7 @@ import AnnotationDetails from "./AnnotationDetails";
110
114
  import AnnotationContent from "./AnnotationContent";
111
115
  import EmptyAnnotation from "./EmptyAnnotation";
112
116
  import AnnotationActionButtons from "./AnnotationActionButtons";
117
+ import { isElementArray } from "../../utils/utils";
113
118
 
114
119
  export default {
115
120
  name: "AnnotationRow",
@@ -162,20 +167,22 @@ export default {
162
167
  "hoveredAnnotationSet",
163
168
  "enableGroupingFeature",
164
169
  "publicView",
165
- "selectedEntities",
166
170
  "newAcceptedAnnotations",
167
171
  "annotationsMarkedAsMissing",
168
172
  "documentId",
169
173
  "showActionError",
170
174
  "missingAnnotations",
171
175
  ]),
172
- ...mapState("selection", ["spanSelection", "elementSelected"]),
176
+ ...mapState("selection", [
177
+ "spanSelection",
178
+ "elementSelected",
179
+ "selectedEntities",
180
+ ]),
173
181
  ...mapGetters("document", [
174
182
  "isAnnotationInEditMode",
175
183
  "annotationIsNotFound",
176
184
  "isDocumentReviewed",
177
185
  ]),
178
- ...mapGetters("selection", ["isValueArray"]),
179
186
  defaultSpan() {
180
187
  if (
181
188
  this.annotation &&
@@ -189,15 +196,11 @@ export default {
189
196
  spanForEditing() {
190
197
  return (
191
198
  this.spanSelection &&
192
- this.isValueArray(this.spanSelection) &&
199
+ isElementArray(this.spanSelection) &&
193
200
  this.isAnnotationInEditMode(this.annotationId())
194
201
  );
195
202
  },
196
- spanFromSelectedEntities() {
197
- return this.selectedEntities.flatMap((ann) => {
198
- return { ...ann.entity.original, offset_string: ann.content };
199
- });
200
- },
203
+
201
204
  isAnnotation() {
202
205
  return (
203
206
  this.annotation &&
@@ -232,24 +235,28 @@ export default {
232
235
  if (
233
236
  newSidebarAnnotationSelected &&
234
237
  this.annotation &&
235
- this.annotation.id === newSidebarAnnotationSelected.id
238
+ this.annotation.id === newSidebarAnnotationSelected.annotation.id
236
239
  ) {
237
240
  clearTimeout(this.annotationAnimationTimeout);
238
241
 
239
- const runAnimation = () => {
240
- this.$el.scrollIntoView({
241
- behavior: "smooth",
242
- block: "center",
243
- inline: "nearest",
244
- });
245
- this.isSelected = true;
246
- // remove annotation selection after some time
247
- this.annotationAnimationTimeout = setTimeout(() => {
248
- this.$store.dispatch("document/setSidebarAnnotationSelected", null);
249
- this.isSelected = false;
250
- }, 1500);
251
- };
252
- runAnimation();
242
+ this.isSelected = true;
243
+ // remove annotation selection after some time
244
+ this.annotationAnimationTimeout = setTimeout(() => {
245
+ this.$store.dispatch("document/setSidebarAnnotationSelected", null);
246
+ this.isSelected = false;
247
+ }, 1500);
248
+
249
+ // Check if sidebarAnnotationSelected changed from a click or hover
250
+ if (newSidebarAnnotationSelected.trigger === "click") {
251
+ const runAnimation = () => {
252
+ this.$el.scrollIntoView({
253
+ behavior: "smooth",
254
+ block: "center",
255
+ inline: "nearest",
256
+ });
257
+ };
258
+ runAnimation();
259
+ }
253
260
  }
254
261
  },
255
262
  editAnnotation(newValue) {
@@ -277,7 +284,22 @@ export default {
277
284
  this.isLoading = false;
278
285
  }
279
286
  },
287
+ selectedEntities(newValue) {
288
+ if (!newValue) return;
289
+
290
+ if (this.isAnnotationInEditMode(this.annotationId())) {
291
+ this.isLoading = true;
292
+ }
293
+ },
294
+ spanSelection(newValue, oldValue) {
295
+ // check if spanSelection has new value from entity selection
296
+ // to stop loading after the text appears in the field
297
+ if (newValue) {
298
+ this.isLoading = false;
299
+ }
300
+ },
280
301
  },
302
+
281
303
  methods: {
282
304
  annotationId() {
283
305
  if (!this.annotationSet || !this.label) return;
@@ -355,6 +377,7 @@ export default {
355
377
  },
356
378
  showAcceptButton() {
357
379
  return (
380
+ !this.editAnnotation &&
358
381
  !this.isAnnotationInEditMode(this.annotationId()) &&
359
382
  this.annotation &&
360
383
  !this.annotation.revised &&
@@ -363,6 +386,7 @@ export default {
363
386
  },
364
387
  showDeclineButton() {
365
388
  return (
389
+ !this.editAnnotation &&
366
390
  !this.isAnnotationInEditMode(this.annotationId()) &&
367
391
  this.annotation &&
368
392
  this.hoveredAnnotation === this.annotation.id
@@ -370,6 +394,7 @@ export default {
370
394
  },
371
395
  showMissingButton() {
372
396
  return (
397
+ !this.editAnnotation &&
373
398
  this.hoveredAnnotation &&
374
399
  !this.isAnnotationInEditMode(this.annotationId()) &&
375
400
  !this.annotation &&
@@ -378,6 +403,7 @@ export default {
378
403
  },
379
404
  showRestoreButton() {
380
405
  return (
406
+ !this.editAnnotation &&
381
407
  this.hoveredAnnotation &&
382
408
  !this.isAnnotationInEditMode(this.annotationId()) &&
383
409
  this.annotationIsNotFound(this.annotationSet, this.label)
@@ -391,7 +417,7 @@ export default {
391
417
  }
392
418
  },
393
419
  showSaveButton() {
394
- if (!this.editAnnotation || this.isLoading) return;
420
+ if (!this.editAnnotation || this.isLoading || !this.spanSelection) return;
395
421
 
396
422
  // Check if it's an Annotation or Empty Annotation
397
423
  if (this.isAnnotation) {
@@ -399,22 +425,18 @@ export default {
399
425
  } else {
400
426
  if (!this.isAnnotationInEditMode(this.annotationId())) return;
401
427
 
402
- // Check if an entity was selected instead of bbox
403
- if (this.selectedEntities && this.selectedEntities.length > 0) {
404
- return this.elementSelected === this.annotationId();
405
- } else {
406
- // Check if an entity was selected instead of bbox
407
- return (
408
- this.elementSelected === this.annotationId() &&
409
- this.spanSelection &&
410
- Array.isArray(this.spanSelection)
411
- );
412
- }
428
+ return (
429
+ this.elementSelected === this.annotationId() &&
430
+ this.spanSelection &&
431
+ Array.isArray(this.spanSelection)
432
+ );
413
433
  }
414
434
  },
415
435
  handleMissingAnnotation() {
416
436
  if (!this.label || !this.annotationSet) return;
417
437
 
438
+ this.isLoading = true;
439
+
418
440
  // will emit to the DocumentAnnotations component, where the method is handled
419
441
  // & dispatched to the store
420
442
  this.$parent.$emit(
@@ -475,77 +497,38 @@ export default {
475
497
  },
476
498
  handleSaveAnnotationChanges(
477
499
  annotation,
478
- spanIndex,
500
+ index,
479
501
  annotationSpan,
480
- annotationText
502
+ annotationContent
481
503
  ) {
482
- let updatedString;
483
-
504
+ // This function deals with declining Annotations
505
+ // or editing an Annotation or a part of it (if multi line)
484
506
  this.isLoading = true;
485
507
 
486
- // Check if we are deleting a single annotation that it's not multi-lined
487
- let isToDelete =
488
- annotationText.length === 0 &&
489
- (!this.isValueArray(annotation.span) || annotation.span.length === 1);
508
+ let updatedString; // what will be sent to the API
509
+ let storeAction; // if it will be 'delete' or 'patch'
490
510
 
491
- let storeAction;
511
+ // Validate if we are deleting an Annotation that it's not multi-lined
512
+ let isToDelete =
513
+ annotationContent.length === 0 &&
514
+ (!isElementArray(annotation.span) || annotation.span.length === 1);
492
515
 
516
+ // Verify if we delete the entire Annotation or a part of the text
493
517
  if (isToDelete || this.toDecline) {
494
518
  storeAction = "document/deleteAnnotation";
495
519
  } else {
520
+ // Editing the Annotation
521
+ // Deleting part of multi-line Annotation
496
522
  storeAction = "document/updateAnnotation";
497
523
 
498
524
  let spans = [...annotation.span];
499
525
 
500
- // Validations to consider span as an array (multiline annotations) or object
501
- if (annotationText.length === 0 && this.isValueArray(annotation.span)) {
502
- // if the annotation content in one row was deleted
503
- // check if it it part of an array
504
- // to only remove that string
505
- spans.splice(spanIndex, 1);
506
- } else if (
507
- this.spanSelection &&
508
- this.isValueArray(this.spanSelection)
509
- ) {
510
- let span;
511
-
512
- // Check if editing was from selecting an entity
513
- if (this.selectedEntities && this.selectedEntities.length > 0) {
514
- span = this.spanFromSelectedEntities;
515
- } else {
516
- spans = [...this.spanSelection];
517
- span = this.createSpan(
518
- this.spanSelection[spanIndex],
519
- annotationText
520
- );
521
- }
526
+ const span = this.createSpan(annotationSpan, annotationContent);
522
527
 
523
- // span is array, only update current one
524
- spans[spanIndex] = {
525
- ...spans[spanIndex],
526
- span,
527
- };
528
- } else {
529
- // if span is NOT an array, but an object
530
- let span;
531
-
532
- if (this.selectedEntities && this.selectedEntities.length > 0) {
533
- spans = this.spanFromSelectedEntities;
534
- } else if (this.spanSelection) {
535
- span = this.createSpan(this.spanSelection, annotationText);
536
-
537
- spans[spanIndex] = {
538
- ...spans[spanIndex],
539
- ...span,
540
- };
541
- } else {
542
- span = this.createSpan(annotationSpan, annotationText);
543
-
544
- spans[spanIndex] = {
545
- ...spans[spanIndex],
546
- ...span,
547
- };
548
- }
528
+ spans[index] = span;
529
+
530
+ if (annotationContent.length === 0) {
531
+ spans.splice(index, 1);
549
532
  }
550
533
 
551
534
  updatedString = {
@@ -571,13 +554,13 @@ export default {
571
554
  .finally(() => {
572
555
  this.$store.dispatch("document/resetEditAnnotation");
573
556
  this.$store.dispatch("selection/disableSelection");
574
- this.$store.dispatch("document/setSelectedEntities", null);
557
+ this.$store.dispatch("selection/setSelectedEntities", null);
575
558
  this.toDecline = false;
576
559
  });
577
560
  },
578
- createSpan(span, annotationText) {
561
+ createSpan(span, annotationContent) {
579
562
  return {
580
- offset_string: annotationText,
563
+ offset_string: annotationContent,
581
564
  page_index: span.page_index,
582
565
  x0: span.x0,
583
566
  x1: span.x1,
@@ -589,18 +572,11 @@ export default {
589
572
  },
590
573
  saveEmptyAnnotationChanges() {
591
574
  let annotationToCreate;
592
- let span;
593
-
594
- if (this.selectedEntities && this.selectedEntities.length > 0) {
595
- span = this.spanFromSelectedEntities;
596
- } else {
597
- span = this.spanSelection;
598
- }
599
575
 
600
576
  if (this.annotationSet.id) {
601
577
  annotationToCreate = {
602
578
  document: this.documentId,
603
- span: span,
579
+ span: this.spanSelection,
604
580
  label: this.label.id,
605
581
  annotation_set: this.annotationSet.id,
606
582
  is_correct: true,
@@ -610,7 +586,7 @@ export default {
610
586
  // if annotation set id is null
611
587
  annotationToCreate = {
612
588
  document: this.documentId,
613
- span: span,
589
+ span: this.spanSelection,
614
590
  label: this.label.id,
615
591
  label_set: this.annotationSet.label_set.id,
616
592
  is_correct: true,
@@ -637,7 +613,7 @@ export default {
637
613
  this.$store.dispatch("document/resetEditAnnotation");
638
614
  if (this.elementSelected) {
639
615
  this.$store.dispatch("selection/disableSelection");
640
- this.$store.dispatch("document/setSelectedEntities", null);
616
+ this.$store.dispatch("selection/setSelectedEntities", null);
641
617
  }
642
618
  },
643
619
  enableLoading(annotations) {
@@ -91,7 +91,10 @@
91
91
  </div>
92
92
 
93
93
  <div v-for="label in annotationSet.labels" :key="label.id">
94
- <div class="labels">
94
+ <div
95
+ class="labels"
96
+ v-if="!(label.annotations.length === 0 && publicView)"
97
+ >
95
98
  <DocumentLabel
96
99
  :label="label"
97
100
  :annotation-set="annotationSet"
@@ -385,14 +388,16 @@ export default {
385
388
  },
386
389
  ];
387
390
  } else if (this.editAnnotation && this.editAnnotation.id !== null) {
388
- // iif annotation is marked as missing from "delete" key
391
+ // if annotation is marked as missing from "delete" key
389
392
 
390
- missing = {
391
- document: parseInt(this.documentId),
392
- label: this.editAnnotation.label,
393
- label_set: this.editAnnotation.labelSet,
394
- annotation_set: this.editAnnotation.annotationSet,
395
- };
393
+ missing = [
394
+ {
395
+ document: parseInt(this.documentId),
396
+ label: this.editAnnotation.label,
397
+ label_set: this.editAnnotation.labelSet,
398
+ annotation_set: this.editAnnotation.annotationSet,
399
+ },
400
+ ];
396
401
  } else if (annotationSet && markAllMissing) {
397
402
  // mark all annotations as missing in annotation set
398
403
 
@@ -447,6 +452,8 @@ export default {
447
452
  })
448
453
  .finally(() => {
449
454
  this.$store.dispatch("document/setAnnotationsMarkedAsMissing", null);
455
+ this.$store.dispatch("document/resetEditAnnotation");
456
+ this.$store.dispatch("selection/disableSelection");
450
457
  });
451
458
  },
452
459