@konfuzio/document-validation-ui 0.2.0-dev.1 → 0.2.0

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.2.0-dev.1",
3
+ "version": "0.2.0",
4
4
  "repository": "https://github.com/konfuzio-ai/document-validation-ui",
5
5
  "main": "dist/app.js",
6
6
  "scripts": {
@@ -35,7 +35,7 @@
35
35
  "sass-loader": "^16.0.5",
36
36
  "splitpanes": "^3.1.8",
37
37
  "vue": "^3.5.13",
38
- "vue-i18n": "^10.0.5",
38
+ "vue-i18n": "^10.0.6",
39
39
  "vue-konva": "^3.2.0",
40
40
  "vue3-observe-visibility": "^1.0.3",
41
41
  "vuedraggable": "^4.1.0",
package/src/api.js CHANGED
@@ -75,6 +75,18 @@ const makeFileRequest = (fileUrl) => {
75
75
  resolve(myBlob);
76
76
  })
77
77
  .catch((error) => {
78
+ if (error.response.status === 428) {
79
+ // retry request after 2 seconds
80
+ setTimeout(() => {
81
+ makeFileRequest(fileUrl)
82
+ .then((response) => {
83
+ resolve(response);
84
+ })
85
+ .catch((error) => {
86
+ reject(error);
87
+ });
88
+ }, 2000);
89
+ }
78
90
  reject(error);
79
91
  });
80
92
  });
@@ -4,6 +4,23 @@
4
4
  align-items: center;
5
5
  gap: 6px;
6
6
 
7
+ .ann-nav-btns {
8
+ display: flex;
9
+ flex-direction: column;
10
+ color: variables.$grey-blue;
11
+ font-size: 14px;
12
+ text-align: center;
13
+ padding-right: 8px;
14
+
15
+ .button-icon {
16
+ width: 12px !important;
17
+ height: 12px !important;
18
+ &.is-link {
19
+ cursor: pointer !important;
20
+ }
21
+ }
22
+ }
23
+
7
24
  .button-action {
8
25
  padding: 0px;
9
26
  vertical-align: middle;
@@ -44,6 +61,10 @@
44
61
  width: 16px;
45
62
  height: 16px;
46
63
  }
64
+ &.angle-icon {
65
+ width: 12px;
66
+ height: 12px;
67
+ }
47
68
  }
48
69
 
49
70
  .button-text {
@@ -66,6 +87,7 @@
66
87
  .search-icon,
67
88
  .missing-icon,
68
89
  .link-icon,
90
+ .angle-icon,
69
91
  .spinner-icon {
70
92
  color: variables.$grey-blue;
71
93
  }
@@ -3,11 +3,9 @@
3
3
  #document-annotations {
4
4
  font-family: variables.$font-family;
5
5
  background-color: variables.$background;
6
- overflow-y: auto;
7
6
  position: relative;
8
7
  display: flex;
9
8
  flex-direction: column;
10
- height: 100%;
11
9
 
12
10
  &.disabled {
13
11
  pointer-events: none;
@@ -217,7 +215,7 @@
217
215
  bottom: 0px;
218
216
  left: 4px;
219
217
  right: 16px;
220
- padding: 0 20%;
218
+ margin: 0 20%;
221
219
  display: flex;
222
220
  align-items: center;
223
221
  border-radius: 8px;
@@ -379,17 +377,17 @@
379
377
  outline: none;
380
378
  }
381
379
 
382
- .label-empty {
383
- font-weight: 500;
384
- font-size: 14px;
385
- color: variables.$primary;
386
- }
387
-
388
380
  .label-empty-clicked {
389
381
  user-select: auto;
390
382
  font-weight: 400;
391
383
  color: variables.$text-lighter;
392
384
  }
385
+
386
+ .label-empty {
387
+ font-weight: 500;
388
+ font-size: 14px;
389
+ color: variables.$primary;
390
+ }
393
391
  }
394
392
  }
395
393
 
@@ -23,6 +23,11 @@
23
23
  background-size: 9px 9px;
24
24
  }
25
25
 
26
+ .document-sidebar {
27
+ overflow-y: auto;
28
+ background-color: variables.$background;
29
+ }
30
+
26
31
  @media print {
27
32
  .dashboard-document {
28
33
  position: static;
@@ -1,5 +1,22 @@
1
1
  <template>
2
2
  <div class="action-buttons">
3
+ <!-- label multi false nav buttons -->
4
+ <b-tooltip
5
+ v-if="isLabelMultiFalseAndGroupOfAnns(label) && !showSave"
6
+ :delay="tooltipDelay"
7
+ position="is-left"
8
+ :label="$t('nav_label_anns')"
9
+ >
10
+ <div class="ann-nav-btns">
11
+ <span>{{ label.annotations.length }}</span>
12
+ <b-icon
13
+ icon="angle-down"
14
+ class="angle-icon center-icon button-icon is-link"
15
+ @click.stop="nextAnn"
16
+ />
17
+ </div>
18
+ </b-tooltip>
19
+
3
20
  <!-- link button -->
4
21
  <b-button
5
22
  v-if="showLink"
@@ -211,7 +228,10 @@ export default {
211
228
  },
212
229
  computed: {
213
230
  ...mapState("document", ["publicView"]),
214
- ...mapGetters("document", ["isDocumentReviewed"]),
231
+ ...mapGetters("document", [
232
+ "isDocumentReviewed",
233
+ "isLabelMultiFalseAndGroupOfAnns",
234
+ ]),
215
235
  showHoverButton() {
216
236
  return (
217
237
  !this.isLoading &&
@@ -257,6 +277,12 @@ export default {
257
277
  link() {
258
278
  this.$emit("link");
259
279
  },
280
+ nextAnn() {
281
+ this.$store.dispatch(
282
+ "document/putNextAnnotationInLabelFirst",
283
+ this.label
284
+ );
285
+ },
260
286
  },
261
287
  };
262
288
  </script>
@@ -171,6 +171,7 @@
171
171
  >
172
172
  <AnnotationActionButtons
173
173
  :annotation="annotation"
174
+ :label="label"
174
175
  :show-cancel="showCancelButton()"
175
176
  :show-accept="showAcceptButton()"
176
177
  :show-decline="showDeclineButton()"
@@ -257,7 +258,6 @@ export default {
257
258
  "editAnnotation",
258
259
  "annotationId",
259
260
  "hoveredAnnotationSet",
260
- "enableGroupingFeature",
261
261
  "publicView",
262
262
  "newAcceptedAnnotations",
263
263
  "annotationsMarkedAsMissing",
@@ -691,12 +691,13 @@ export default {
691
691
 
692
692
  // check if annotation set was changed
693
693
  if (
694
- (this.editAnnotation.annotationSet &&
694
+ !isToDecline &&
695
+ ((this.editAnnotation.annotationSet &&
695
696
  (this.editAnnotation.annotationSet.id !== this.annotationSet.id ||
696
697
  (this.editAnnotation.annotationSet.id == null &&
697
698
  this.labelSet.id !== this.editAnnotation.labelSet.id))) ||
698
- (this.editAnnotation.label &&
699
- this.editAnnotation.label.id !== this.label.id)
699
+ (this.editAnnotation.label &&
700
+ this.editAnnotation.label.id !== this.label.id))
700
701
  ) {
701
702
  // first delete annotation, then create new one
702
703
  this.$store
@@ -1,43 +1,8 @@
1
1
  <template>
2
2
  <div class="label">
3
- <div
4
- v-if="isGroup"
5
- :class="['label-group', !showAnnotationsGroup && 'keyboard-nav']"
6
- @click.stop="toggleGroup"
7
- >
8
- <div class="label-group-left">
9
- <b-icon
10
- :icon="showAnnotationsGroup ? 'angle-up' : 'angle-down'"
11
- size="is-16"
12
- class="caret"
13
- />
14
- <div class="label-name">
15
- <span>{{ `${label.name} (${label.annotations.length})` }}</span>
16
- </div>
17
- </div>
18
- <div class="label-group-right">
19
- <div v-if="!publicView" class="label-annotations-pending">
20
- {{
21
- `${label.annotations.length - acceptedAnnotationsGroupCounter} ${$t(
22
- "annotations_pending"
23
- )}`
24
- }}
25
- </div>
26
- <div v-if="!publicView" class="label-annotations-accepted">
27
- {{
28
- `${acceptedAnnotationsGroupCounter} ${$t("annotations_accepted")}`
29
- }}
30
- </div>
31
- </div>
32
- </div>
33
- <div
34
- v-if="showAnnotationsGroup && annotationSet"
35
- :class="isGroup && 'label-group-annotation-list'"
36
- >
3
+ <div v-if="annotationSet">
37
4
  <AnnotationRow
38
- v-for="(annotation, index) in hasAnnotations
39
- ? label.annotations
40
- : [singleAnnotation]"
5
+ v-for="(annotation, index) in annotationsToShow()"
41
6
  :key="index"
42
7
  :annotation="annotation"
43
8
  :label="label"
@@ -45,7 +10,7 @@
45
10
  :label-set="annotationSet.label_set"
46
11
  />
47
12
  </div>
48
- <div v-else-if="showAnnotationsGroup && labelSet">
13
+ <div v-else-if="labelSet">
49
14
  <AnnotationRow :label="label" :label-set="labelSet" />
50
15
  </div>
51
16
  </div>
@@ -74,94 +39,19 @@ export default {
74
39
  required: true,
75
40
  },
76
41
  },
77
- data() {
78
- return {
79
- nonMultipleAnnotationsExtracted: false,
80
- acceptedAnnotationsGroupCounter: 0,
81
- showAnnotationsGroup: false,
82
- };
83
- },
84
42
  computed: {
85
- ...mapState("document", [
86
- "annotationId",
87
- "enableGroupingFeature",
88
- "hoveredAnnotationSet",
89
- "publicView",
43
+ ...mapState("document", ["annotationId", "publicView"]),
44
+ ...mapGetters("document", [
45
+ "numberOfAcceptedAnnotationsInLabel",
46
+ "isLabelMultiFalseAndGroupOfAnns",
90
47
  ]),
91
- ...mapGetters("document", ["numberOfAcceptedAnnotationsInLabel"]),
92
- singleAnnotation() {
93
- if (this.label.annotations && this.label.annotations.length > 0) {
94
- return this.label.annotations[0];
95
- }
96
- return null;
97
- },
98
- hasAnnotations() {
99
- return this.label.annotations && this.label.annotations.length > 0;
100
- },
101
- isGroup() {
102
- return this.enableGroupingFeature && this.nonMultipleAnnotationsExtracted;
103
- },
104
- },
105
- watch: {
106
- annotationId(newAnnotationId) {
107
- this.checkAnnotationSelected(newAnnotationId);
108
- },
109
- hoveredAnnotationSet(newValue) {
110
- // Check if there are some unrevised Annotations within the group
111
- if (
112
- newValue &&
113
- newValue.type === "accept" &&
114
- this.labelHasPendingAnnotations(newValue)
115
- ) {
116
- this.showAnnotationsGroup = true;
117
- }
118
- },
119
- },
120
- mounted() {
121
- this.updateValues();
122
- this.checkAnnotationSelected(this.annotationId);
123
-
124
- if (this.publicView) {
125
- this.showAnnotationsGroup = true;
126
- }
127
- },
128
- updated() {
129
- this.updateValues();
130
48
  },
131
49
  methods: {
132
- checkAnnotationSelected(newAnnotationId) {
133
- // check if annotation is inside a label group and open it
134
- if (
135
- this.enableGroupingFeature &&
136
- !this.showAnnotationsGroup &&
137
- newAnnotationId
138
- ) {
139
- const annotation = this.label.annotations.find(
140
- (ann) => ann.id == newAnnotationId
141
- );
142
-
143
- if (annotation) {
144
- this.showAnnotationsGroup = true;
145
- }
146
- }
147
- },
148
- toggleGroup() {
149
- this.showAnnotationsGroup = !this.showAnnotationsGroup;
150
- },
151
- updateValues() {
152
- // more than 1 Annotation extracted for a non multiple Label
153
- this.nonMultipleAnnotationsExtracted =
154
- this.label.annotations &&
155
- this.label.annotations.length > 1 &&
156
- !this.label.has_multiple_top_candidates;
157
-
158
- if (this.nonMultipleAnnotationsExtracted) {
159
- this.acceptedAnnotationsGroupCounter =
160
- this.numberOfAcceptedAnnotationsInLabel(this.label);
161
- }
162
- if (!this.isGroup) {
163
- // if not a group then show by default
164
- this.showAnnotationsGroup = true;
50
+ annotationsToShow() {
51
+ if (this.isLabelMultiFalseAndGroupOfAnns(this.label)) {
52
+ return [this.label.annotations[0]];
53
+ } else {
54
+ return this.label.annotations;
165
55
  }
166
56
  },
167
57
  labelHasPendingAnnotations(hoveredSet) {
@@ -10,7 +10,7 @@
10
10
  class="dashboard-document"
11
11
  />
12
12
  </pane>
13
- <pane :size="50">
13
+ <pane :size="50" class="document-sidebar">
14
14
  <DocumentAnnotations v-if="!editMode" ref="annotations" />
15
15
  <DocumentEdit v-else ref="editView" />
16
16
  </pane>
@@ -59,11 +59,6 @@
59
59
  />
60
60
  <div class="switch-info">
61
61
  <span class="switch-text">{{ $t("smart_split") }}</span>
62
- <span
63
- v-if="documentHasProposedSplit(selectedDocument)"
64
- class="new-badge"
65
- >{{ newText }}</span
66
- >
67
62
  </div>
68
63
  </b-field>
69
64
  </b-tooltip>
@@ -93,7 +88,6 @@ export default {
93
88
  return {
94
89
  buttonDisabled: true,
95
90
  tooltipInfo: null,
96
- newText: this.$t("new"),
97
91
  switchStatus: true,
98
92
  };
99
93
  },
@@ -129,9 +123,6 @@ export default {
129
123
  this.$nextTick(() => {
130
124
  this.switchStatus = this.splitSuggestionsEnabled;
131
125
  this.tooltipInfo = this.$t("no_splitting_suggestions");
132
- if (this.newText) {
133
- this.newText = this.$t("new").toUpperCase();
134
- }
135
126
  });
136
127
  },
137
128
  methods: {
@@ -17,6 +17,7 @@
17
17
  v-model="textFromEntities"
18
18
  class="popup-input"
19
19
  type="text"
20
+ :disabled="true"
20
21
  />
21
22
  </div>
22
23
  <b-dropdown
@@ -105,6 +105,7 @@ export default {
105
105
  data() {
106
106
  return {
107
107
  currentPercentage: 100,
108
+ fitWidthScale: 1, // baseline for 100%
108
109
  maxPercentage: 500,
109
110
  defaultPercentage: 0.25,
110
111
  fitPercentage: 0.5,
@@ -136,6 +137,13 @@ export default {
136
137
  this.editModeDisabled = true;
137
138
  }
138
139
  },
140
+ scale(newScale) {
141
+ if (this.fitWidthScale > 0) {
142
+ this.currentPercentage = Math.round((newScale / this.fitWidthScale) * 100);
143
+ } else {
144
+ this.currentPercentage = Math.round(newScale * 100);
145
+ }
146
+ },
139
147
  },
140
148
  mounted() {
141
149
  if (this.selectedDocument) {
@@ -178,12 +186,13 @@ export default {
178
186
  this.updateScale(this.scale - this.defaultPercentage);
179
187
  },
180
188
  fitAuto() {
181
- // exit edit mode of Annotation if changing zoom during editing
182
189
  this.cancelAnnotationEditMode();
183
-
184
- // Always set to 50%
185
- this.currentPercentage = 50;
186
- this.$store.dispatch("display/updateFit", "all");
190
+ this.$store.dispatch("display/updateFit", "all").then(() => {
191
+ this.$nextTick(() => {
192
+ this.fitWidthScale = this.scale;
193
+ this.currentPercentage = 100;
194
+ });
195
+ });
187
196
  },
188
197
  updateScale(scale) {
189
198
  this.$store.dispatch("display/updateFit", "custom").then(() => {
@@ -1,7 +1,7 @@
1
1
  <template>
2
- <div>
2
+ <div v-observe-visibility="visibilityChanged">
3
3
  <DummyPage
4
- v-if="!loadedPage || !pageInVisibleRange(page)"
4
+ v-if="!loadedPage"
5
5
  :width="page.size[0]"
6
6
  :height="page.size[1]"
7
7
  />
@@ -179,6 +179,14 @@ export default {
179
179
  this.pageBeingLoaded = false;
180
180
  });
181
181
  },
182
+ visibilityChanged(isVisible) {
183
+ if (isVisible && !this.loadedPage && !this.pageBeingLoaded) {
184
+ this.loadPage();
185
+ }
186
+ if (!isVisible && this.loadedPage) {
187
+ this.$store.dispatch("document/unloadDocumentPage", this.page.number);
188
+ }
189
+ },
182
190
  pageInVisibleRange(page) {
183
191
  return (
184
192
  this.currentPage === page.number ||
@@ -166,5 +166,6 @@
166
166
  "checkbox_ann_details": "Für dieses Label wird ein Kästchen extrahiert.",
167
167
  "document_section": "Dokumentabschnitt",
168
168
  "label_size": "Spaltengröße:",
169
- "powered_by": "betrieben von Konfuzio"
169
+ "powered_by": "betrieben von Konfuzio",
170
+ "nav_label_anns": "Durch Annotationen navigieren"
170
171
  }
@@ -167,5 +167,6 @@
167
167
  "checkbox_ann_details": "A checkbox will be extracted for this label.",
168
168
  "document_section": "Document Section",
169
169
  "label_size": "Column size:",
170
- "powered_by": "powered by Konfuzio"
170
+ "powered_by": "powered by Konfuzio",
171
+ "nav_label_anns": "Navigate through annotations"
171
172
  }
@@ -166,5 +166,6 @@
166
166
  "checkbox_ann_details": "Se extraerá una casilla de verificación para esta etiqueta.",
167
167
  "document_section": "Sección del documento",
168
168
  "label_size": "Tamaño de columna:",
169
- "powered_by": "impulsado por Konfuzio"
169
+ "powered_by": "impulsado por Konfuzio",
170
+ "nav_label_anns": "Navegar por las anotaciones"
170
171
  }
@@ -270,11 +270,8 @@ const actions = {
270
270
  commit("SET_SCALE", autoScale);
271
271
  break;
272
272
  case "all": {
273
- commit(
274
- "SET_SCALE",
275
- getters.pageWidthScale(elementsWidth, client.width, viewport.width) -
276
- 0.5
277
- );
273
+ const widthScale = getters.pageWidthScale(elementsWidth, client.width, viewport.width);
274
+ commit("SET_SCALE", widthScale);
278
275
  break;
279
276
  }
280
277
  case "custom": {