@konfuzio/document-validation-ui 0.1.1 → 0.1.2-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.
Files changed (39) hide show
  1. package/dist/css/app.6a102cfe.css +1 -0
  2. package/dist/index.html +1 -1
  3. package/dist/js/app.de7765e6.js +2 -0
  4. package/dist/js/app.de7765e6.js.map +1 -0
  5. package/dist/js/{chunk-vendors.a48fca3f.js → chunk-vendors.dbed2bf7.js} +2 -2
  6. package/dist/js/chunk-vendors.dbed2bf7.js.map +1 -0
  7. package/package.json +4 -4
  8. package/src/assets/scss/annotation_details.scss +1 -1
  9. package/src/assets/scss/categorize_modal.scss +36 -33
  10. package/src/assets/scss/choose_label_set_modal.scss +60 -57
  11. package/src/assets/scss/document_page.scss +4 -0
  12. package/src/assets/scss/document_top_bar.scss +0 -7
  13. package/src/assets/scss/variables.scss +47 -29
  14. package/src/components/DocumentAnnotations/ActionButtons.vue +33 -21
  15. package/src/components/DocumentAnnotations/AnnotationDetails.vue +66 -109
  16. package/src/components/DocumentAnnotations/CategorizeModal.vue +91 -32
  17. package/src/components/DocumentAnnotations/ChooseLabelSetModal.vue +56 -27
  18. package/src/components/DocumentAnnotations/DocumentAnnotations.vue +0 -14
  19. package/src/components/DocumentEdit/DocumentEdit.vue +25 -36
  20. package/src/components/DocumentEdit/EditPages.vue +8 -17
  21. package/src/components/DocumentPage/DocumentPage.vue +17 -16
  22. package/src/components/DocumentPage/DocumentToolbar.vue +12 -24
  23. package/src/components/DocumentPage/NewAnnotation.vue +11 -2
  24. package/src/components/DocumentPage/ScrollingPage.vue +4 -17
  25. package/src/components/DocumentTopBar/DocumentTopBar.vue +0 -15
  26. package/src/components/DocumentTopBar/DocumentTopBarButtons.vue +7 -2
  27. package/src/components/DocumentTopBar/index.js +0 -2
  28. package/src/locales/de.json +8 -5
  29. package/src/locales/en.json +6 -3
  30. package/src/locales/es.json +6 -3
  31. package/src/store/document.js +88 -9
  32. package/dist/css/app.0c8973f8.css +0 -1
  33. package/dist/js/app.17fe48c4.js +0 -2
  34. package/dist/js/app.17fe48c4.js.map +0 -1
  35. package/dist/js/chunk-vendors.a48fca3f.js.map +0 -1
  36. package/src/assets/scss/document_dataset_status.scss +0 -46
  37. package/src/assets/scss/document_handover.scss +0 -200
  38. package/src/components/DocumentTopBar/DocumentDatasetStatus.vue +0 -103
  39. package/src/components/DocumentTopBar/DocumentHandover.vue +0 -202
@@ -1,14 +1,13 @@
1
1
  <template>
2
2
  <b-tooltip
3
- type="is-dark"
4
3
  :animated="false"
5
4
  position="is-bottom"
6
5
  class="left-aligned annotation-details"
7
6
  >
8
7
  <div class="label-icon">
9
- <div v-if="created || edited">
8
+ <div v-if="created(annotation) || edited(annotation)">
10
9
  <div
11
- v-if="accepted"
10
+ v-if="accepted(annotation)"
12
11
  :class="[
13
12
  'annotation-details-icon',
14
13
  animate ? 'animated-ripple' : '',
@@ -29,7 +28,7 @@
29
28
  </div>
30
29
  </div>
31
30
  <div
32
- v-else-if="notFound"
31
+ v-else-if="notFound(annotation)"
33
32
  :class="[
34
33
  'annotation-details-icon',
35
34
  animate ? 'animated-ripple' : '',
@@ -40,8 +39,11 @@
40
39
  </div>
41
40
  <div v-else>
42
41
  <div
43
- v-if="accepted"
44
- :class="['annotation-details-icon', animate ? 'animated-ripple' : '']"
42
+ v-if="accepted(annotation)"
43
+ :class="[
44
+ 'annotation-details-icon success',
45
+ animate ? 'animated-ripple' : '',
46
+ ]"
45
47
  >
46
48
  <AcceptedCheckMark />
47
49
  </div>
@@ -59,21 +61,25 @@
59
61
  <div v-if="description" class="label-description">
60
62
  <span>{{ description }}</span>
61
63
  </div>
62
- <div v-if="accuracy" class="accuracy">
63
- <span>{{ $t("accuracy") }}</span
64
+ <div v-if="confidence(annotation)" class="confidence">
65
+ <span>{{ $t("confidence") }}</span
64
66
  ><span
65
67
  :class="[
66
68
  'value',
67
- accuracy <= 0.2 ? 'red' : accuracy <= 0.5 ? 'yellow' : '',
69
+ confidence(annotation) <= 0.2
70
+ ? 'red'
71
+ : confidence(annotation) <= 0.5
72
+ ? 'yellow'
73
+ : '',
68
74
  ]"
69
- >{{ Math.floor(accuracy * 100) / 100 }}</span
75
+ >{{ Math.floor(confidence(annotation) * 100) / 100 }}</span
70
76
  >
71
77
  </div>
72
78
  <div class="revision">
73
79
  <div class="detail-icons">
74
- <div v-if="created || edited">
80
+ <div v-if="created(annotation) || edited(annotation)">
75
81
  <div
76
- v-if="accepted"
82
+ v-if="accepted(annotation)"
77
83
  :class="[
78
84
  'annotation-details-icon',
79
85
  animate ? 'animated-ripple' : '',
@@ -94,7 +100,7 @@
94
100
  </div>
95
101
  </div>
96
102
  <div
97
- v-else-if="notFound"
103
+ v-else-if="notFound(annotation)"
98
104
  :class="[
99
105
  'annotation-details-icon',
100
106
  animate ? 'animated-ripple' : '',
@@ -105,7 +111,7 @@
105
111
  </div>
106
112
  <div v-else>
107
113
  <div
108
- v-if="accepted"
114
+ v-if="accepted(annotation)"
109
115
  :class="[
110
116
  'annotation-details-icon',
111
117
  animate ? 'animated-ripple' : '',
@@ -131,6 +137,7 @@
131
137
  </b-tooltip>
132
138
  </template>
133
139
  <script>
140
+ import { mapGetters } from "vuex";
134
141
  import CheckMark from "../../assets/images/CheckMark";
135
142
  import AcceptedCheckMark from "../../assets/images/AcceptedCheckMark";
136
143
  import QuestionMark from "../../assets/images/QuestionMark";
@@ -163,97 +170,23 @@ export default {
163
170
  };
164
171
  },
165
172
  computed: {
166
- accuracy() {
167
- // TODO: add this verification to store
168
- if (this.annotation) {
169
- return this.annotation.confidence;
170
- } else {
171
- return null;
172
- }
173
- },
174
- notFound() {
175
- // TODO: add this verification to store
176
- if (this.annotation) {
177
- return !this.annotation.span;
178
- } else {
179
- return true;
180
- }
181
- },
182
- created() {
183
- // TODO: add this verification to store
184
- if (this.annotation) {
185
- return (
186
- this.annotation.created_by &&
187
- !this.annotation.revised &&
188
- this.annotation.is_correct
189
- );
190
- } else {
191
- return null;
192
- }
193
- },
194
- edited() {
195
- // TODO: add this verification to store
196
- if (this.annotation) {
197
- if (
198
- this.annotation.offset_string !==
199
- this.annotation.offset_string_original
200
- ) {
201
- return true;
202
- } else if (this.annotation.created_by) {
203
- return true;
204
- } else {
205
- return false;
206
- }
207
- } else {
208
- return null;
209
- }
210
- },
211
- accepted() {
212
- // TODO: add this verification to store
213
- if (this.annotation) {
214
- return this.annotation.revised && this.annotation.is_correct;
215
- } else {
216
- return null;
217
- }
218
- },
219
- declined() {
220
- // TODO: add this verification to store
221
- if (this.annotation) {
222
- return this.annotation.revised && !this.annotation.is_correct;
223
- } else {
224
- return null;
225
- }
226
- },
227
- user() {
228
- // TODO: add this verification to store
229
- if (this.annotation) {
230
- if (this.annotation.created_by && !this.annotation.revised) {
231
- // If the annotation was created but not yet revised
232
- // we show who created it
233
- return this.annotation.created_by;
234
- } else if (this.annotation.revised && this.annotation.revised_by) {
235
- return this.annotation.revised_by;
236
- } else {
237
- // If both revised_by and created_by are null, we don't show any user
238
- return null;
239
- }
240
- } else {
241
- return null;
242
- }
243
- },
173
+ ...mapGetters("document", [
174
+ "confidence",
175
+ "notFound",
176
+ "created",
177
+ "edited",
178
+ "accepted",
179
+ "getUser",
180
+ ]),
244
181
  },
245
182
  watch: {
246
183
  annotation(newAnnotation, oldAnnotation) {
247
184
  // animate an annotation being accepted
248
- // TODO: add this accepted check to store
249
- const accepted = (ann) => {
250
- return ann && ann.id && ann.revised && ann.is_correct;
251
- };
252
185
  if (
253
186
  newAnnotation &&
254
187
  newAnnotation.id &&
255
- accepted(newAnnotation) &&
256
- !accepted(oldAnnotation)
188
+ this.accepted(newAnnotation) &&
189
+ !this.accepted(oldAnnotation)
257
190
  ) {
258
191
  this.animate = true;
259
192
  setTimeout(() => {
@@ -262,26 +195,50 @@ export default {
262
195
  }
263
196
  },
264
197
  },
198
+ mounted() {
199
+ this.changePositionOfTooltip();
200
+ },
265
201
  methods: {
266
202
  getText() {
267
- if (this.notFound) {
203
+ if (this.notFound(this.annotation)) {
268
204
  return this.$t("not_found_in_document");
269
- } else if (this.created) {
270
- return this.user
271
- ? `${this.$t("created_by")} ${this.user}`
205
+ } else if (this.created(this.annotation)) {
206
+ return this.getUser(this.annotation)
207
+ ? `${this.$t("created_by")} ${this.getUser(this.annotation)}`
272
208
  : this.$t("created");
273
- } else if (this.accepted) {
274
- return this.user
275
- ? `${this.$t("approved_by")} ${this.user}`
209
+ } else if (this.accepted(this.annotation)) {
210
+ return this.getUser(this.annotation)
211
+ ? `${this.$t("approved_by")} ${this.getUser(this.annotation)}`
276
212
  : this.$t("approved");
277
- } else if (this.declined) {
278
- return this.user
279
- ? `${this.$t("declined_by")} ${this.user}`
280
- : this.$t("declined");
281
213
  } else {
282
214
  return this.$t("not_revised_yet");
283
215
  }
284
216
  },
217
+ changePositionOfTooltip() {
218
+ // Get all elements
219
+ const annDetails = document.getElementsByClassName("annotation-details");
220
+
221
+ // Only last 3 rows will change the position
222
+ if (annDetails) {
223
+ let lastElementsInList;
224
+
225
+ if (annDetails.length >= 3) {
226
+ lastElementsInList = annDetails.length - 2;
227
+ } else {
228
+ return;
229
+ }
230
+
231
+ for (let i = lastElementsInList; i < annDetails.length; i++) {
232
+ this.updateClass(annDetails, i);
233
+ }
234
+ }
235
+ },
236
+ updateClass(array, index) {
237
+ if (!array[index]) return;
238
+
239
+ array[index].classList.remove("is-bottom");
240
+ array[index].classList.add("is-top");
241
+ },
285
242
  },
286
243
  };
287
244
  </script>
@@ -6,7 +6,7 @@
6
6
  :can-cancel="canCloseModal()"
7
7
  class="modal-absolute modal-400 modal-no-footer"
8
8
  >
9
- <section class="modal-card-body">
9
+ <section class="modal-card-body scroll-hidden">
10
10
  <div class="content">
11
11
  <h3>{{ $t("categorize_document_title") }}</h3>
12
12
  <p v-if="documentCategory">
@@ -17,31 +17,51 @@
17
17
  <p v-else>
18
18
  {{ $t("not_categorized") }}
19
19
  </p>
20
- <b-dropdown
21
- v-model="selectedCategory"
22
- aria-role="list"
23
- class="categorize-dropdown"
20
+
21
+ <b-tooltip
22
+ multilined
23
+ :active="singleCategoryInProject"
24
+ size="is-large"
25
+ position="is-bottom"
26
+ class="bottom-aligned"
27
+ :close-delay="5000"
24
28
  >
25
- <template #trigger>
26
- <div class="category-dropdown">
27
- <div>
28
- <span v-if="selectedCategory">{{
29
- selectedCategory.name
30
- }}</span>
31
- <span v-else>{{ $t("choose_category") }}</span>
32
- </div>
33
- </div>
29
+ <template #content>
30
+ <div ref="tooltipContent"></div>
34
31
  </template>
35
- <b-dropdown-item
36
- v-for="categoryItem in categories"
37
- :key="categoryItem.id"
38
- aria-role="listitem"
39
- :value="categoryItem"
40
- @click="setSelectedCategory(categoryItem)"
32
+ <b-dropdown
33
+ v-model="selectedCategory"
34
+ aria-role="list"
35
+ :class="[
36
+ 'categorize-dropdown',
37
+ singleCategoryInProject && 'dropdown-disabled',
38
+ ]"
39
+ :disabled="singleCategoryInProject"
41
40
  >
42
- <span>{{ categoryItem.name }}</span>
43
- </b-dropdown-item>
44
- </b-dropdown>
41
+ <template #trigger>
42
+ <div class="category-dropdown">
43
+ <div>
44
+ <span v-if="selectedCategory">{{
45
+ selectedCategory.name
46
+ }}</span>
47
+ <span v-else-if="singleCategoryInProject">{{
48
+ categories[0].name
49
+ }}</span>
50
+ <span v-else>{{ $t("choose_category") }}</span>
51
+ </div>
52
+ </div>
53
+ </template>
54
+ <b-dropdown-item
55
+ v-for="categoryItem in categories"
56
+ :key="categoryItem.id"
57
+ aria-role="listitem"
58
+ :value="categoryItem"
59
+ @click="setSelectedCategory(categoryItem)"
60
+ >
61
+ <span>{{ categoryItem.name }}</span>
62
+ </b-dropdown-item>
63
+ </b-dropdown>
64
+ </b-tooltip>
45
65
  <div v-if="selectedCategory" class="category-description">
46
66
  {{
47
67
  selectedCategory.description
@@ -75,12 +95,6 @@ import { mapGetters, mapState } from "vuex";
75
95
 
76
96
  export default {
77
97
  name: "CategorizeModal",
78
- computed: {
79
- ...mapState("category", ["categories"]),
80
- ...mapState("document", ["selectedDocument"]),
81
- ...mapGetters("category", ["category"]),
82
- ...mapGetters("document", ["categorizationIsConfirmed"]),
83
- },
84
98
  data() {
85
99
  return {
86
100
  show: false,
@@ -88,6 +102,17 @@ export default {
88
102
  documentCategory: null, // category associated to document
89
103
  };
90
104
  },
105
+ computed: {
106
+ ...mapState("category", ["categories"]),
107
+ ...mapState("document", ["selectedDocument"]),
108
+ ...mapGetters("category", ["category"]),
109
+ ...mapGetters("document", ["categorizationIsConfirmed"]),
110
+
111
+ singleCategoryInProject() {
112
+ // if only 1 category in the project, we don't enable the dropdown
113
+ return this.categories && this.categories.length === 1;
114
+ },
115
+ },
91
116
  watch: {
92
117
  selectedDocument(newValue) {
93
118
  if (newValue) {
@@ -97,18 +122,43 @@ export default {
97
122
  categories(newCategories, oldCategories) {
98
123
  if (newCategories && oldCategories === null) {
99
124
  this.setDocumentValues();
125
+
126
+ if (newCategories.length === 1) {
127
+ this.setTooltipText();
128
+ }
100
129
  }
101
130
  },
131
+ show(newValue) {
132
+ this.$store.dispatch("document/setCategorizeModalIsActive", newValue);
133
+ },
102
134
  },
103
135
  mounted() {
104
136
  this.setDocumentValues();
137
+
138
+ this.$nextTick(() => {
139
+ this.setTooltipText();
140
+ });
141
+ },
142
+ updated() {
143
+ this.setTooltipText();
105
144
  },
106
145
  methods: {
107
146
  setDocumentValues() {
108
147
  if (this.selectedDocument) {
109
- const category = this.category(this.selectedDocument.category);
148
+ let category;
149
+
150
+ // Check if the document has an extracted category
151
+ // or if it doesn't, but the project has only 1 category
152
+ if (this.selectedDocument.category) {
153
+ category = this.category(this.selectedDocument.category);
154
+ this.documentCategory = category;
155
+ } else if (this.categories && this.categories.length === 1) {
156
+ category = this.category(this.categories[0].id);
157
+ } else {
158
+ category = category;
159
+ }
160
+
110
161
  this.selectedCategory = category;
111
- this.documentCategory = category;
112
162
  this.show = !this.categorizationIsConfirmed;
113
163
  }
114
164
  },
@@ -123,7 +173,8 @@ export default {
123
173
  (this.selectedCategory &&
124
174
  this.documentCategory &&
125
175
  this.selectedCategory.id !== this.documentCategory.id) ||
126
- (this.selectedCategory && !this.documentCategory)
176
+ (this.selectedCategory && !this.documentCategory) ||
177
+ (this.selectedCategory && this.singleCategoryInProject)
127
178
  ) {
128
179
  const updatedCategory = {
129
180
  category: this.selectedCategory.id,
@@ -152,6 +203,14 @@ export default {
152
203
  }
153
204
  this.show = false;
154
205
  },
206
+ setTooltipText() {
207
+ // Text set from innerHTML vs 'label' due to html tag in locales file string
208
+ if (this.singleCategoryInProject && this.show) {
209
+ this.$refs.tooltipContent.innerHTML = this.$t(
210
+ "single_category_in_project"
211
+ );
212
+ }
213
+ },
155
214
  },
156
215
  };
157
216
  </script>
@@ -23,32 +23,47 @@
23
23
  : $t("new_ann_set_description")
24
24
  }}
25
25
  </p>
26
- <b-dropdown
27
- v-model="selectedLabelSet"
28
- aria-role="list"
29
- :disabled="labelSets.length === 0"
30
- class="label-set-dropdown"
26
+ <b-tooltip
27
+ multilined
28
+ :active="labelSets.length === 0"
29
+ size="is-large"
30
+ position="is-bottom"
31
+ class="bottom-aligned"
32
+ :close-delay="5000"
31
33
  >
32
- <template #trigger>
33
- <div>
34
- <div>
35
- <span v-if="selectedLabelSet">{{
36
- selectedLabelSet.name
37
- }}</span>
38
- <span v-else>{{ $t("select_label_set") }}</span>
39
- </div>
40
- </div>
34
+ <template #content>
35
+ <div ref="tooltipContent"></div>
41
36
  </template>
42
- <b-dropdown-item
43
- v-for="labelSetItem in labelSets"
44
- :key="labelSetItem.id"
45
- aria-role="listitem"
46
- :value="labelSetItem"
47
- @click="setSelectedLabelSet(labelSetItem)"
37
+ <b-dropdown
38
+ v-model="selectedLabelSet"
39
+ aria-role="list"
40
+ :disabled="labelSets.length === 0"
41
+ :class="[
42
+ 'label-set-dropdown',
43
+ labelSets.length === 0 && 'dropdown-disabled',
44
+ ]"
48
45
  >
49
- <span>{{ labelSetItem.name }}</span>
50
- </b-dropdown-item>
51
- </b-dropdown>
46
+ <template #trigger>
47
+ <div>
48
+ <div>
49
+ <span v-if="selectedLabelSet">{{
50
+ selectedLabelSet.name
51
+ }}</span>
52
+ <span v-else>{{ $t("select_label_set") }}</span>
53
+ </div>
54
+ </div>
55
+ </template>
56
+ <b-dropdown-item
57
+ v-for="labelSetItem in labelSets"
58
+ :key="labelSetItem.id"
59
+ aria-role="listitem"
60
+ :value="labelSetItem"
61
+ @click="setSelectedLabelSet(labelSetItem)"
62
+ >
63
+ <span>{{ labelSetItem.name }}</span>
64
+ </b-dropdown-item>
65
+ </b-dropdown>
66
+ </b-tooltip>
52
67
  <div v-if="selectedLabelSet" class="labels-list">
53
68
  <div v-if="isMultipleAnnotations" class="labels-select">
54
69
  <div v-for="label in labels" :key="label.id">
@@ -90,12 +105,9 @@ import { mapGetters, mapState } from "vuex";
90
105
 
91
106
  export default {
92
107
  name: "CreateAnnotationSetModal",
93
- computed: {
94
- ...mapState("document", ["annotationSets"]),
95
- ...mapGetters("project", ["labelSetsFilteredForAnnotationSetCreation"]),
96
- },
97
108
  props: {
98
109
  isMultipleAnnotations: {
110
+ type: Boolean,
99
111
  default: false,
100
112
  required: false,
101
113
  },
@@ -108,6 +120,17 @@ export default {
108
120
  labels: [],
109
121
  };
110
122
  },
123
+ computed: {
124
+ ...mapState("document", ["annotationSets"]),
125
+ ...mapGetters("project", ["labelSetsFilteredForAnnotationSetCreation"]),
126
+ },
127
+ watch: {
128
+ labelSets(newValue) {
129
+ if (newValue.length === 0) {
130
+ this.setTooltipText();
131
+ }
132
+ },
133
+ },
111
134
  mounted() {
112
135
  this.$store.dispatch("project/fetchLabelSets").then((data) => {
113
136
  this.labelSets = this.labelSetsFilteredForAnnotationSetCreation(
@@ -144,6 +167,12 @@ export default {
144
167
  };
145
168
  });
146
169
  },
170
+ setTooltipText() {
171
+ // Text set from innerHTML vs 'label' due to html tag in locales file string
172
+ this.$refs.tooltipContent.innerHTML = this.$t(
173
+ "no_multi_ann_labelset_model"
174
+ );
175
+ },
147
176
  },
148
177
  };
149
178
  </script>
@@ -144,20 +144,6 @@ export default {
144
144
  }
145
145
  },
146
146
  },
147
- watch: {
148
- editAnnotation(newValue) {
149
- if (!newValue && !this.jumpToNextAnnotation) {
150
- this.count = 0;
151
- }
152
- },
153
- acceptAnnotation(newValue, oldValue) {
154
- // TODO: rework this to be more generic
155
- if (!newValue && oldValue) {
156
- this.focusOnNextAnnotation();
157
- this.jumpToNextAnnotation = false;
158
- }
159
- },
160
- },
161
147
  created() {
162
148
  window.addEventListener("keydown", this.keyDownHandler);
163
149
  },