@konfuzio/document-validation-ui 0.1.21 → 0.1.22-dev.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@konfuzio/document-validation-ui",
3
- "version": "0.1.21",
3
+ "version": "0.1.22-dev.1",
4
4
  "repository": "git://github.com:konfuzio-ai/document-validation-ui.git",
5
5
  "main": "dist/app.js",
6
6
  "scripts": {
@@ -51,6 +51,7 @@
51
51
 
52
52
  .annotation-set-group {
53
53
  .label-set-header {
54
+ cursor: pointer;
54
55
  display: flex;
55
56
  align-items: center;
56
57
  justify-content: space-between;
@@ -66,6 +67,14 @@
66
67
  font-size: 14px;
67
68
  line-height: 20px;
68
69
  color: $text;
70
+ display: flex;
71
+ align-items: center;
72
+ gap: 8px;
73
+
74
+ .icon {
75
+ width: 12px;
76
+ height: 12px;
77
+ }
69
78
  }
70
79
  }
71
80
 
@@ -300,32 +300,22 @@ export default {
300
300
  ) {
301
301
  clearTimeout(this.annotationAnimationTimeout);
302
302
 
303
- let timeout;
304
-
305
- if (!newSidebarAnnotationSelected.trigger) {
306
- timeout = 600;
307
- } else {
308
- timeout = 1200;
309
- }
310
-
311
303
  this.isSelected = true;
312
304
  // remove annotation selection after some time
313
305
  this.annotationAnimationTimeout = setTimeout(() => {
314
306
  this.$store.dispatch("document/setSidebarAnnotationSelected", null);
315
307
  this.isSelected = false;
316
- }, timeout);
308
+ }, 1200);
317
309
 
318
310
  // Check if sidebarAnnotationSelected changed from a click or hover
319
- if (newSidebarAnnotationSelected.trigger === "click") {
320
- const runAnimation = () => {
321
- this.$el.scrollIntoView({
322
- behavior: "smooth",
323
- block: "center",
324
- inline: "nearest",
325
- });
326
- };
327
- runAnimation();
328
- }
311
+ const runAnimation = () => {
312
+ this.$el.scrollIntoView({
313
+ behavior: "smooth",
314
+ block: "center",
315
+ inline: "nearest",
316
+ });
317
+ };
318
+ runAnimation();
329
319
  }
330
320
  },
331
321
  editAnnotation(newValue) {
@@ -49,12 +49,22 @@
49
49
  </div>
50
50
  </div>
51
51
  <div
52
- v-for="(annotationSet, indexGroup) in annotationSetsToShowInList()"
52
+ v-for="(annotationSet, indexGroup) in annotationSets"
53
53
  :key="indexGroup"
54
- class="annotation-set-group"
54
+ :class="[
55
+ 'annotation-set-group',
56
+ !annotationSetsAccordion[indexGroup] === true &&
57
+ 'annotation-set-collapsed',
58
+ ]"
55
59
  >
56
- <div class="label-set-header">
60
+ <div class="label-set-header" @click="toggleAccordion(indexGroup)">
57
61
  <div class="label-set-name">
62
+ <b-icon
63
+ :icon="
64
+ annotationSetsAccordion[indexGroup] ? 'angle-up' : 'angle-down'
65
+ "
66
+ >
67
+ </b-icon>
58
68
  {{
59
69
  `${annotationSet.label_set.name} ${numberOfAnnotationSetGroup(
60
70
  annotationSet
@@ -66,6 +76,7 @@
66
76
  class="labelset-action-buttons"
67
77
  >
68
78
  <AnnotationSetActionButtons
79
+ v-if="annotationSetsAccordion[indexGroup] === true"
69
80
  :number-of-empty-labels-in-annotation-set="
70
81
  emptyLabels(annotationSet).length
71
82
  "
@@ -92,34 +103,38 @@
92
103
  </div>
93
104
  </div>
94
105
 
95
- <div v-if="annotationSet.labels.length > 0">
96
- <div v-for="label in annotationSet.labels" :key="label.id">
97
- <div
98
- v-if="!(label.annotations.length === 0 && publicView)"
99
- class="labels"
100
- >
101
- <DocumentLabel
102
- :label="label"
103
- :annotation-set="annotationSet"
104
- :index-group="indexGroup"
105
- @handle-missing-annotation="markAnnotationsAsMissing"
106
- />
106
+ <b-collapse :open="annotationSetsAccordion[indexGroup] === true">
107
+ <div v-if="annotationSet.labels.length > 0">
108
+ <div v-for="label in annotationSet.labels" :key="label.id">
109
+ <div
110
+ v-if="!(label.annotations.length === 0 && publicView)"
111
+ class="labels"
112
+ >
113
+ <DocumentLabel
114
+ :label="label"
115
+ :annotation-set="annotationSet"
116
+ :index-group="indexGroup"
117
+ @handle-missing-annotation="markAnnotationsAsMissing"
118
+ />
119
+ </div>
107
120
  </div>
108
121
  </div>
109
- </div>
110
122
 
111
- <div v-if="annotationSet.labels.length === 0" class="no-labels">
112
- <span> {{ $t("no_labels_in_set") }}</span>
113
- <!-- eslint-disable-next-line vue/no-v-html -->
114
- <span v-if="isDocumentEditable" v-html="$t('link_to_add_labels')" />
115
- </div>
123
+ <div v-if="annotationSet.labels.length === 0" class="no-labels">
124
+ <span> {{ $t("no_labels_in_set") }}</span>
125
+ <!-- eslint-disable-next-line vue/no-v-html -->
126
+ <span v-if="isDocumentEditable" v-html="$t('link_to_add_labels')" />
127
+ </div>
116
128
 
117
- <div
118
- v-else-if="!annotationSetHasAnnotations(annotationSet) && publicView"
119
- class="no-labels"
120
- >
121
- <span> {{ $t("no_annotations_in_annotation_set") }}</span>
122
- </div>
129
+ <div
130
+ v-else-if="
131
+ !annotationSetHasAnnotations(annotationSet) && publicView
132
+ "
133
+ class="no-labels"
134
+ >
135
+ <span> {{ $t("no_annotations_in_annotation_set") }}</span>
136
+ </div>
137
+ </b-collapse>
123
138
  </div>
124
139
  </div>
125
140
  </div>
@@ -150,6 +165,7 @@ export default {
150
165
  count: 0,
151
166
  jumpToNextAnnotation: false,
152
167
  numberOfLoadingAnnotations: 3,
168
+ annotationSetsAccordion: [],
153
169
  };
154
170
  },
155
171
  computed: {
@@ -166,15 +182,16 @@ export default {
166
182
  "labels",
167
183
  "selectedDocument",
168
184
  "splittingSuggestions",
185
+ "sidebarAnnotationSelected",
169
186
  ]),
170
187
  ...mapGetters("category", ["category"]),
171
188
  ...mapGetters("document", [
172
189
  "numberOfAnnotationSetGroup",
173
190
  "emptyLabels",
174
191
  "notCorrectAnnotations",
175
- "annotationSetsToShowInList",
176
192
  "annotationSetsInTable",
177
193
  "isDocumentReviewed",
194
+ "annotationSetOfAnnotation",
178
195
  ]),
179
196
  isAnnotationBeingEdited() {
180
197
  return this.editAnnotation && this.editAnnotation.id;
@@ -195,6 +212,70 @@ export default {
195
212
  this.jumpToNextAnnotation = false;
196
213
  }
197
214
  },
215
+ annotationSets(newAnnotationSets, oldAnnotationSets) {
216
+ if (newAnnotationSets) {
217
+ const newAnnotationSetsAccordion = [];
218
+ const annotationSetsOpened = [];
219
+ const annotationSetsCreated = [];
220
+ if (oldAnnotationSets) {
221
+ // when annotation sets changed, restore old state
222
+ // and check if new ones were created to be open by default
223
+
224
+ this.annotationSetsAccordion.forEach((isOpen, index) => {
225
+ if (isOpen) {
226
+ annotationSetsOpened.push(oldAnnotationSets[index]);
227
+ }
228
+ });
229
+
230
+ newAnnotationSets.forEach((newAnnotationSet) => {
231
+ const existed = oldAnnotationSets.find(
232
+ (oldAnnotationSet) =>
233
+ oldAnnotationSet.id &&
234
+ newAnnotationSet.id &&
235
+ oldAnnotationSet.id === newAnnotationSet.id
236
+ );
237
+ if (!existed && newAnnotationSet.id !== null) {
238
+ annotationSetsCreated.push(newAnnotationSet);
239
+ }
240
+ });
241
+ }
242
+
243
+ newAnnotationSets.forEach((newAnnotationSet, index) => {
244
+ const wasOpen = annotationSetsOpened.find(
245
+ (annotationSetOpened) =>
246
+ annotationSetOpened.id &&
247
+ newAnnotationSet.id &&
248
+ newAnnotationSet.id === annotationSetOpened.id
249
+ );
250
+
251
+ if (wasOpen) {
252
+ newAnnotationSetsAccordion[index] = wasOpen !== undefined;
253
+ } else {
254
+ const wasCreated = annotationSetsCreated.find(
255
+ (annotationSetCreated) =>
256
+ annotationSetCreated.id &&
257
+ newAnnotationSet.id &&
258
+ newAnnotationSet.id === annotationSetCreated.id
259
+ );
260
+ newAnnotationSetsAccordion[index] = wasCreated !== undefined;
261
+ }
262
+ });
263
+ this.annotationSetsAccordion = newAnnotationSetsAccordion;
264
+ }
265
+ },
266
+ sidebarAnnotationSelected(annotation) {
267
+ if (annotation) {
268
+ const annotationSet = this.annotationSetOfAnnotation(annotation);
269
+ if (annotationSet) {
270
+ const index = this.annotationSets.findIndex(
271
+ (annotationSetToFind) => annotationSetToFind.id === annotationSet.id
272
+ );
273
+ const newAnnotationSetsAccordion = [...this.annotationSetsAccordion];
274
+ newAnnotationSetsAccordion[index] = true;
275
+ this.annotationSetsAccordion = newAnnotationSetsAccordion;
276
+ }
277
+ }
278
+ },
198
279
  },
199
280
  created() {
200
281
  window.addEventListener("keydown", this.keyDownHandler);
@@ -203,6 +284,18 @@ export default {
203
284
  window.removeEventListener("keydown", this.keyDownHandler);
204
285
  },
205
286
  methods: {
287
+ toggleAccordion(index) {
288
+ const newAnnotationSetsAccordion = [...this.annotationSetsAccordion];
289
+ newAnnotationSetsAccordion[index] = !newAnnotationSetsAccordion[index];
290
+ this.annotationSetsAccordion = newAnnotationSetsAccordion;
291
+ },
292
+ openAllAccordions() {
293
+ const newAnnotationSetsAccordion = [...this.annotationSetsAccordion];
294
+ newAnnotationSetsAccordion.forEach((_, index) => {
295
+ newAnnotationSetsAccordion[index] = true;
296
+ });
297
+ this.annotationSetsAccordion = newAnnotationSetsAccordion;
298
+ },
206
299
  annotationSetHasAnnotations(annotationSet) {
207
300
  const found = annotationSet.labels.find(
208
301
  (label) => label.annotations.length > 0
@@ -280,6 +373,10 @@ export default {
280
373
 
281
374
  // Not allow starting edit mode with ArrowUp key
282
375
  if (event.key === "ArrowUp" && !this.isAnnotationBeingEdited) return;
376
+
377
+ // open accordions
378
+ this.openAllAccordions();
379
+
283
380
  // Get all the annotation elements
284
381
  let annotations = this.createArray("keyboard-nav");
285
382
 
@@ -297,7 +394,9 @@ export default {
297
394
  if (this.count >= annotations.length) {
298
395
  const finishBtn = this.createArray("finish-review-btn");
299
396
 
300
- finishBtn[0].focus();
397
+ if (finishBtn && finishBtn[0]) {
398
+ finishBtn[0].focus();
399
+ }
301
400
  this.$store.dispatch("document/resetEditAnnotation");
302
401
  this.count = 0;
303
402
  if (event.key === "Enter" && !finishBtn.disabled) {
@@ -71,8 +71,8 @@
71
71
  v-if="!isAnnotationInEditMode(annotation.id)"
72
72
  :key="'ann' + annotation.id + '-' + index"
73
73
  :config="annotationRect(bbox, annotation.id)"
74
- @click="handleFocusedAnnotation(annotation, 'click')"
75
- @mouseenter="handleFocusedAnnotation(annotation)"
74
+ @click="handleFocusedAnnotation(annotation)"
75
+ @mouseenter="onElementEnter"
76
76
  @mouseleave="onElementLeave"
77
77
  />
78
78
  </template>
@@ -396,17 +396,9 @@ export default {
396
396
  });
397
397
  },
398
398
 
399
- handleFocusedAnnotation(annotation, trigger) {
400
- this.$store.dispatch("document/setSidebarAnnotationSelected", {
401
- annotation,
402
- trigger,
403
- });
404
-
405
- if (trigger && trigger === "click") {
406
- this.closePopups(true);
407
- } else {
408
- this.onElementEnter();
409
- }
399
+ handleFocusedAnnotation(annotation) {
400
+ this.$store.dispatch("document/setSidebarAnnotationSelected", annotation);
401
+ this.closePopups(true);
410
402
  },
411
403
 
412
404
  handleClickedEntity(entity) {
@@ -247,6 +247,28 @@ const getters = {
247
247
  return annotations;
248
248
  },
249
249
 
250
+ /* Get annotation set for a given annotation */
251
+ annotationSetOfAnnotation: (state) => (annotationToFind) => {
252
+ let foundAnnotationSet = null;
253
+ state.annotationSets.forEach((annotationSet) => {
254
+ annotationSet.labels.forEach((label) => {
255
+ label.annotations.forEach((annotation) => {
256
+ if (annotation.id === annotationToFind.id) {
257
+ foundAnnotationSet = annotationSet;
258
+ return;
259
+ }
260
+ });
261
+ if (foundAnnotationSet) {
262
+ return;
263
+ }
264
+ });
265
+ if (foundAnnotationSet) {
266
+ return;
267
+ }
268
+ });
269
+ return foundAnnotationSet;
270
+ },
271
+
250
272
  /* Process annotations and extract labels and sets */
251
273
  processAnnotationSets: (state, getters) => (annotationSets) => {
252
274
  // group annotations for sidebar