@konfuzio/document-validation-ui 0.1.45-dev.0 → 0.1.45

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.45-dev.0",
3
+ "version": "0.1.45",
4
4
  "repository": "git://github.com:konfuzio-ai/document-validation-ui.git",
5
5
  "main": "dist/app.js",
6
6
  "scripts": {
package/src/api.js CHANGED
@@ -4,7 +4,8 @@ let HTTP, FILE_REQUEST, authToken, appLocale;
4
4
  const DEFAULT_URL = "https://app.konfuzio.com";
5
5
  const FILE_URL = process.env.VUE_APP_IMAGE_URL;
6
6
 
7
- axios.defaults.withCredentials = true;
7
+ axios.defaults.xsrfCookieName = "csrftoken";
8
+ axios.defaults.xsrfHeaderName = "X-CSRFToken";
8
9
 
9
10
  HTTP = axios.create({
10
11
  baseURL: process.env.VUE_APP_API_URL || `${DEFAULT_URL}/api/v3/`,
@@ -34,9 +35,8 @@ const setLocale = (locale) => {
34
35
  const getInterceptorConfig = (config) => {
35
36
  if (authToken) {
36
37
  config.headers["Authorization"] = `Token ${authToken}`;
38
+ config.headers["Accept-Language"] = `${appLocale}-${appLocale}`;
37
39
  }
38
- config.headers["Accept-Language"] = `${appLocale}-${appLocale}`;
39
-
40
40
  return config;
41
41
  };
42
42
 
@@ -67,11 +67,45 @@ const makeFileRequest = (fileUrl) => {
67
67
  });
68
68
  };
69
69
 
70
+ const makeGetPaginatedRequest = (request, hasParams = false) => {
71
+ let returnResponse = [];
72
+ let toFinishLoop = false;
73
+
74
+ let separator = hasParams ? "&" : "?";
75
+ let loopRequest = `${request}${separator}limit=100`;
76
+
77
+ return new Promise(async (resolve, reject) => {
78
+ do {
79
+ try {
80
+ let response = await HTTP.get(loopRequest);
81
+ if (response && response.data) {
82
+ const data = response.data;
83
+ if (data.results) {
84
+ returnResponse = [...returnResponse, ...data.results];
85
+ }
86
+ if (data.next) {
87
+ loopRequest = data.next;
88
+ } else {
89
+ toFinishLoop = true;
90
+ }
91
+ } else {
92
+ reject("Error getting paginated results.");
93
+ }
94
+ } catch (error) {
95
+ reject(error);
96
+ console.log(error);
97
+ }
98
+ } while (!toFinishLoop);
99
+ resolve(returnResponse);
100
+ });
101
+ };
102
+
70
103
  export default {
71
104
  HTTP,
72
105
  setApiUrl,
73
106
  setFileUrl,
74
107
  makeFileRequest,
108
+ makeGetPaginatedRequest,
75
109
  setAuthToken,
76
110
  setLocale,
77
111
  FILE_REQUEST,
@@ -0,0 +1,19 @@
1
+ @import "./imports.scss";
2
+ .document-set-dropdown {
3
+ border-right: $component-border;
4
+
5
+ .dropdown-doc-set {
6
+ display: flex;
7
+ margin: 0 16px;
8
+ gap: 8px;
9
+ cursor: pointer;
10
+ justify-content: center;
11
+ align-items: center;
12
+
13
+ .dropdown-text {
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: 4px;
17
+ }
18
+ }
19
+ }
@@ -262,6 +262,12 @@
262
262
  margin-left: 0;
263
263
  }
264
264
 
265
+ &.dropdown-full-width {
266
+ .dropdown-menu {
267
+ width: 100%;
268
+ }
269
+ }
270
+
265
271
  .dropdown-trigger {
266
272
  justify-content: space-between;
267
273
  width: 100%;
@@ -6,13 +6,7 @@
6
6
  :class="['left-aligned', 'annotation-details']"
7
7
  >
8
8
  <div :class="['label-icon']">
9
- <div
10
- v-if="
11
- (created(annotation) || edited(annotation)) &&
12
- !isNegative(annotation) &&
13
- !publicView
14
- "
15
- >
9
+ <div v-if="(created(annotation) || edited(annotation)) && !publicView">
16
10
  <div
17
11
  :class="[
18
12
  'annotation-details-icon',
@@ -30,9 +24,7 @@
30
24
  <NotFoundIcon />
31
25
  </div>
32
26
  <div
33
- v-else-if="
34
- notExtracted(annotation) || (isNegative(annotation) && !publicView)
35
- "
27
+ v-else-if="notExtracted(annotation) && !publicView"
36
28
  :class="[
37
29
  'annotation-details-icon',
38
30
  animate ? 'animated-ripple' : '',
@@ -78,7 +70,7 @@
78
70
  <span>{{ description }}</span>
79
71
  </div>
80
72
  <div
81
- v-if="confidence(annotation) && !isNegative(annotation)"
73
+ v-if="confidence(annotation)"
82
74
  :class="['confidence', publicView && 'tooltip-in-public-view']"
83
75
  >
84
76
  <span>{{ $t("confidence") }}</span
@@ -193,7 +185,6 @@ export default {
193
185
  "created",
194
186
  "edited",
195
187
  "accepted",
196
- "isNegative",
197
188
  "getUser",
198
189
  "annotationIsNotFound",
199
190
  ]),
@@ -220,10 +211,7 @@ export default {
220
211
  },
221
212
  methods: {
222
213
  getText() {
223
- if (
224
- this.notExtracted(this.annotation) ||
225
- this.isNegative(this.annotation)
226
- ) {
214
+ if (this.notExtracted(this.annotation)) {
227
215
  return this.$t("not_found_in_document");
228
216
  } else if (this.created(this.annotation)) {
229
217
  return this.getUser(this.annotation)
@@ -84,10 +84,7 @@
84
84
  </div>
85
85
  <div class="annotation-row-right">
86
86
  <div class="annotation-content">
87
- <div
88
- v-if="annotation && !isNegative(annotation)"
89
- class="annotation-items"
90
- >
87
+ <div v-if="annotation" class="annotation-items">
91
88
  <b-checkbox
92
89
  v-if="annotation.metadata && annotation.metadata.checkbox"
93
90
  v-model="isChecked"
@@ -251,12 +248,10 @@ export default {
251
248
  "isAnnotationInEditMode",
252
249
  "annotationIsNotFound",
253
250
  "isDocumentReviewed",
254
- "isNegative",
255
251
  ]),
256
252
  defaultSpan() {
257
253
  if (
258
254
  this.annotation &&
259
- !this.isNegative(this.annotation) &&
260
255
  this.annotation.span &&
261
256
  this.annotation.span.length > 0
262
257
  ) {
@@ -274,7 +269,6 @@ export default {
274
269
  isAnnotation() {
275
270
  return (
276
271
  this.annotation &&
277
- !this.isNegative(this.annotation) &&
278
272
  this.isAnnotationInEditMode(
279
273
  this.currentAnnotationId(),
280
274
  this.editAnnotation.index
@@ -298,7 +292,6 @@ export default {
298
292
  this.hoveredAnnotationSet &&
299
293
  this.hoveredAnnotationSet.type == "accept" &&
300
294
  this.annotation &&
301
- !this.isNegative(this.annotation) &&
302
295
  this.hoveredNotCorrectAnnotations() === this.annotation.id
303
296
  );
304
297
  },
@@ -395,7 +388,6 @@ export default {
395
388
  if (
396
389
  newAnnotationId &&
397
390
  this.annotation &&
398
- !this.isNegative(this.annotation) &&
399
391
  this.annotation.id == newAnnotationId
400
392
  ) {
401
393
  this.isSelected = true;
@@ -421,12 +413,7 @@ export default {
421
413
  currentAnnotationId() {
422
414
  if ((!this.annotationSet && !this.labelSet) || !this.label) return;
423
415
 
424
- if (
425
- this.annotation &&
426
- this.annotation.id &&
427
- !this.isNegative(this.annotation)
428
- )
429
- return this.annotation.id;
416
+ if (this.annotation && this.annotation.id) return this.annotation.id;
430
417
 
431
418
  const setId = this.annotationSet
432
419
  ? this.annotationSet.id
@@ -461,12 +448,8 @@ export default {
461
448
  }
462
449
  );
463
450
  const found = labels.find((l) => l.id === this.label.id);
464
- const negativeAnnotations = found.annotations.find((annotation) =>
465
- this.isNegative(annotation)
466
- );
467
451
 
468
- if ((found && found.annotations.length === 0) || negativeAnnotations)
469
- return found.id;
452
+ if (found && found.annotations.length === 0) return found.id;
470
453
  return null;
471
454
  },
472
455
  hoveredNotCorrectAnnotations() {
@@ -504,7 +487,6 @@ export default {
504
487
  !this.editAnnotation &&
505
488
  !this.isAnnotationInEditMode(this.currentAnnotationId()) &&
506
489
  this.annotation &&
507
- !this.isNegative(this.annotation) &&
508
490
  !this.annotation.is_correct &&
509
491
  this.hoveredAnnotation === this.annotation.id
510
492
  );
@@ -514,7 +496,6 @@ export default {
514
496
  !this.editAnnotation &&
515
497
  !this.isAnnotationInEditMode(this.currentAnnotationId()) &&
516
498
  this.annotation &&
517
- !this.isNegative(this.annotation) &&
518
499
  this.hoveredAnnotation === this.annotation.id
519
500
  );
520
501
  },
@@ -523,7 +504,7 @@ export default {
523
504
  !this.editAnnotation &&
524
505
  this.hoveredAnnotation &&
525
506
  !this.isAnnotationInEditMode(this.currentAnnotationId()) &&
526
- (!this.annotation || this.isNegative(this.annotation)) &&
507
+ !this.annotation &&
527
508
  !this.annotationIsNotFound(this.annotationSet, this.label)
528
509
  );
529
510
  },
@@ -578,7 +559,6 @@ export default {
578
559
  // Verify if we are editing a filled or empty annotation
579
560
  if (
580
561
  this.annotation &&
581
- !this.isNegative(this.annotation) &&
582
562
  (this.showAcceptButton() ||
583
563
  this.showDeclineButton() ||
584
564
  this.isAnnotationInEditMode(
@@ -619,7 +599,7 @@ export default {
619
599
  this.saveAnnotationChanges(spans, decline);
620
600
  }
621
601
  } else if (
622
- (!this.annotation || this.isNegative(this.annotation)) &&
602
+ !this.annotation &&
623
603
  this.isAnnotationInEditMode(this.currentAnnotationId())
624
604
  ) {
625
605
  this.saveEmptyAnnotationChanges();
@@ -632,7 +612,7 @@ export default {
632
612
  (item) =>
633
613
  item.annotation_set === this.annotationSet.id &&
634
614
  item.label === this.label.id &&
635
- item.label_set === this.annotationSet.labelSet.id
615
+ item.label_set === this.labelSet.id
636
616
  );
637
617
 
638
618
  this.$store
@@ -716,18 +696,10 @@ export default {
716
696
  };
717
697
  }
718
698
  this.isLoading = true;
719
- let negativeAnnotationId;
720
-
721
- // check if the annotation to create comes from a negative annotation
722
- // so we can create the new one and remove the negative one from the annotations array
723
- if (this.isNegative(this.annotation)) {
724
- negativeAnnotationId = this.annotation.id;
725
- }
726
699
 
727
700
  this.$store
728
701
  .dispatch("document/createAnnotation", {
729
702
  annotation: annotationToCreate,
730
- negativeAnnotationId: negativeAnnotationId,
731
703
  })
732
704
  .catch((error) => {
733
705
  this.$store.dispatch("document/createErrorMessage", {
@@ -255,7 +255,6 @@ export default {
255
255
  "isDocumentReadyToBeReviewed",
256
256
  "isDocumentReviewed",
257
257
  "labelOfAnnotation",
258
- "isNegative",
259
258
  ]),
260
259
  selectionPage() {
261
260
  return this.selection && this.selection.pageNumber;
@@ -305,8 +304,7 @@ export default {
305
304
  if (
306
305
  annotation.span.find(
307
306
  (span) => span.page_index + 1 === this.page.number
308
- ) &&
309
- !this.isNegative(annotation)
307
+ )
310
308
  ) {
311
309
  annotations.push(annotation);
312
310
  }
@@ -167,7 +167,6 @@ export default {
167
167
  ...mapGetters("document", [
168
168
  "numberOfAnnotationSetGroup",
169
169
  "labelsFilteredForAnnotationCreation",
170
- "isNegative",
171
170
  ]),
172
171
  ...mapGetters("display", ["bboxToRect"]),
173
172
  ...mapState("selection", ["selection", "spanSelection"]),
@@ -285,26 +284,9 @@ export default {
285
284
  annotationToCreate.label_set = this.selectedSet.label_set.id;
286
285
  }
287
286
 
288
- // check if the selected label already has a negative annotation
289
- let negativeAnnotationId;
290
-
291
- if (
292
- this.selectedLabel.annotations &&
293
- this.selectedLabel.annotations.length > 0
294
- ) {
295
- const negativeAnnotation = this.selectedLabel.annotations.find(
296
- (annotation) => this.isNegative(annotation)
297
- );
298
-
299
- if (negativeAnnotation) {
300
- negativeAnnotationId = negativeAnnotation.id;
301
- }
302
- }
303
-
304
287
  this.$store
305
288
  .dispatch("document/createAnnotation", {
306
289
  annotation: annotationToCreate,
307
- negativeAnnotationId: negativeAnnotationId,
308
290
  })
309
291
  .catch((error) => {
310
292
  this.$store.dispatch("document/createErrorMessage", {
@@ -169,7 +169,6 @@ export default {
169
169
  "numberOfAnnotationSetGroup",
170
170
  "numberOfLabelSetGroup",
171
171
  "labelsFilteredForAnnotationCreation",
172
- "isNegative",
173
172
  ]),
174
173
  ...mapGetters("display", ["clientToBbox"]),
175
174
  ...mapState("selection", ["spanSelection", "selection"]),
@@ -294,27 +293,9 @@ export default {
294
293
  } else {
295
294
  annotationToCreate.label_set = this.selectedSet.label_set.id;
296
295
  }
297
-
298
- // check if the selected label already has a negative annotation
299
- let negativeAnnotationId;
300
-
301
- if (
302
- this.selectedLabel.annotations &&
303
- this.selectedLabel.annotations.length > 0
304
- ) {
305
- const negativeAnnotation = this.selectedLabel.annotations.find(
306
- (annotation) => this.isNegative(annotation)
307
- );
308
-
309
- if (negativeAnnotation) {
310
- negativeAnnotationId = negativeAnnotation.id;
311
- }
312
- }
313
-
314
296
  this.$store
315
297
  .dispatch("document/createAnnotation", {
316
298
  annotation: annotationToCreate,
317
- negativeAnnotationId: negativeAnnotationId,
318
299
  })
319
300
  .catch((error) => {
320
301
  this.$store.dispatch("document/createErrorMessage", {
@@ -0,0 +1,88 @@
1
+ <template>
2
+ <b-dropdown
3
+ v-if="
4
+ documentSet && documentSet.documents && documentSet.documents.length > 1
5
+ "
6
+ v-model="selectedDocId"
7
+ class="document-set-dropdown dropdown-full-width"
8
+ aria-role="list"
9
+ scrollable
10
+ >
11
+ <template #trigger>
12
+ <div class="dropdown-doc-set">
13
+ <div class="dropdown-left">
14
+ <CategoryIcon />
15
+ </div>
16
+ <div class="dropdown-text">
17
+ <div class="top-part">
18
+ {{ $t("document_section") }}
19
+ </div>
20
+ <div class="bottom-part">
21
+ {{
22
+ `#${numberOfDocumentInSet(selectedDocument.id)} ${categoryName(
23
+ selectedDocument.category
24
+ )}`
25
+ }}
26
+ </div>
27
+ </div>
28
+ <div class="dropdown-right">
29
+ <b-icon icon="angle-down" size="is-small" class="caret" />
30
+ </div>
31
+ </div>
32
+ </template>
33
+
34
+ <b-dropdown-item
35
+ v-for="doc in documentSet.documents"
36
+ :key="doc.id"
37
+ aria-role="listitem"
38
+ class="list-item"
39
+ :value="doc.id"
40
+ @click="handleDocumentClick(doc)"
41
+ >
42
+ <span>
43
+ {{
44
+ `#${numberOfDocumentInSet(doc.id)} ${categoryName(doc.category)}`
45
+ }}</span
46
+ >
47
+ </b-dropdown-item>
48
+ </b-dropdown>
49
+ </template>
50
+
51
+ <script>
52
+ import { mapGetters, mapState } from "vuex";
53
+ import CategoryIcon from "../../assets/images/CategoryIconImg";
54
+
55
+ export default {
56
+ name: "DocumentSetChooser",
57
+ components: {
58
+ CategoryIcon,
59
+ },
60
+ data() {
61
+ return {
62
+ selectedDocId: 0,
63
+ };
64
+ },
65
+ computed: {
66
+ ...mapGetters("document", ["numberOfDocumentInSet"]),
67
+ ...mapGetters("category", ["categoryName"]),
68
+ ...mapState("document", ["documentSet", "selectedDocument"]),
69
+ },
70
+ mounted() {
71
+ this.selectedDocId = this.selectedDocument.id;
72
+ },
73
+ methods: {
74
+ handleDocumentClick(document) {
75
+ this.$store.dispatch("document/changeCurrentDocument", {
76
+ document,
77
+ documentId: document.id,
78
+ });
79
+ },
80
+ },
81
+ };
82
+ </script>
83
+
84
+ <style
85
+ scoped
86
+ lang="scss"
87
+ src="../../assets/scss/document_set_chooser.scss"
88
+ ></style>
@@ -4,9 +4,9 @@
4
4
  v-if="selectedDocument && selectedDocument.pages.length > 0 && !loading"
5
5
  :class="['document-top-bar', editMode && 'edit-mode-top-bar']"
6
6
  >
7
- <div v-if="!recalculatingAnnotations" class="left-bar-components">
8
- <DocumentCategory
9
- v-if="categories && !editMode && !publicView && !isDocumentReviewed"
7
+ <div class="left-bar-components">
8
+ <DocumentSetChooser
9
+ v-if="!publicView && !recalculatingAnnotations && !editMode"
10
10
  />
11
11
  </div>
12
12
 
@@ -91,7 +91,7 @@
91
91
 
92
92
  <script>
93
93
  import { mapGetters, mapState } from "vuex";
94
- import DocumentCategory from "../../components/DocumentCategory";
94
+ import DocumentSetChooser from "./DocumentSetChooser";
95
95
  import DocumentName from "./DocumentName";
96
96
  import DocumentTopBarButtons from "./DocumentTopBarButtons";
97
97
  import KeyboardActionsDescription from "./KeyboardActionsDescription";
@@ -104,14 +104,13 @@ import KeyboardActionsDescription from "./KeyboardActionsDescription";
104
104
  export default {
105
105
  name: "DocumentTopBar",
106
106
  components: {
107
- DocumentCategory,
107
+ DocumentSetChooser,
108
108
  DocumentName,
109
109
  DocumentTopBarButtons,
110
110
  KeyboardActionsDescription,
111
111
  },
112
112
  data() {
113
113
  return {
114
- categoryError: false,
115
114
  previousDocument: null,
116
115
  nextDocument: null,
117
116
  };
@@ -123,7 +122,6 @@ export default {
123
122
  "loading",
124
123
  "recalculatingAnnotations",
125
124
  ]),
126
- ...mapState("category", ["categories"]),
127
125
  ...mapState("edit", ["editMode"]),
128
126
  ...mapState("project", ["documentsInProject"]),
129
127
  ...mapGetters("document", [
@@ -181,14 +179,9 @@ export default {
181
179
  navigateToDocument(document) {
182
180
  if (!document) return;
183
181
 
184
- this.$store.dispatch("document/changeCurrentDocument", document.id);
185
-
186
- if (this.editMode) {
187
- // Reset edit mode when changing the document,
188
- // in case the change was made from the arrows in the Edit Mode
189
- // so that the user does not get stuck in this interface
190
- this.$store.dispatch("edit/disableEditMode");
191
- }
182
+ this.$store.dispatch("document/changeCurrentDocument", {
183
+ documentId: document.id,
184
+ });
192
185
  },
193
186
  },
194
187
  };
@@ -110,7 +110,7 @@ export default {
110
110
  },
111
111
  methods: {
112
112
  changeDocument(documentId) {
113
- this.$store.dispatch("document/changeCurrentDocument", documentId);
113
+ this.$store.dispatch("document/changeCurrentDocument", { documentId });
114
114
  },
115
115
  requestTrialAccess() {
116
116
  window.open("https://konfuzio.com", "_blank");
@@ -161,5 +161,6 @@
161
161
  "annotation_deleted": "Diese Annotation wurde gelöscht.",
162
162
  "annotation_link": "Kopieren Sie den permanenten Link zu dieser Annotationen",
163
163
  "copied": "Kopiert",
164
- "checkbox_ann_details": "Für dieses Label wird ein Kästchen extrahiert."
164
+ "checkbox_ann_details": "Für dieses Label wird ein Kästchen extrahiert.",
165
+ "document_section": "Dokumentabschnitt"
165
166
  }
@@ -162,5 +162,6 @@
162
162
  "annotation_deleted": "This annotation has been deleted.",
163
163
  "annotation_link": "Copy the permanent link to this annotation",
164
164
  "copied": "Copied",
165
- "checkbox_ann_details": "A checkbox will be extracted for this label."
165
+ "checkbox_ann_details": "A checkbox will be extracted for this label.",
166
+ "document_section": "Document Section"
166
167
  }
@@ -161,5 +161,6 @@
161
161
  "annotation_deleted": "Esta anotación ha sido eliminada.",
162
162
  "annotation_link": "Copia el enlace permanente a esta anotación.",
163
163
  "copied": "Copiada",
164
- "checkbox_ann_details": "Se extraerá una casilla de verificación para esta etiqueta."
164
+ "checkbox_ann_details": "Se extraerá una casilla de verificación para esta etiqueta.",
165
+ "document_section": "Sección del documento"
165
166
  }
@@ -116,9 +116,9 @@ const actions = {
116
116
  if (
117
117
  poll &&
118
118
  rootState.project.documentsInProject.length !==
119
- state.documentsAvailableToReview.length &&
119
+ state.documentsAvailableToReview.length &&
120
120
  state.documentsAvailableToReview.length + errors !==
121
- rootState.project.documentsInProject.length
121
+ rootState.project.documentsInProject.length
122
122
  ) {
123
123
  if (count >= 10) return true;
124
124
 
@@ -136,7 +136,7 @@ const actions = {
136
136
  if (
137
137
  rootState.project.documentsInProject.length === 0 ||
138
138
  rootState.project.documentsInProject.length !==
139
- state.documentsAvailableToReview.length
139
+ state.documentsAvailableToReview.length
140
140
  ) {
141
141
  let duration;
142
142
  if (count <= 5) {
@@ -153,7 +153,8 @@ const actions = {
153
153
  },
154
154
 
155
155
  fetchCategories: ({ commit }, projectId) => {
156
- return HTTP.get(`categories/?limit=100&project=${projectId}`)
156
+ return myImports
157
+ .makeGetPaginatedRequest(`categories/?project=${projectId}`, true)
157
158
  .then(async (response) => {
158
159
  if (response.data && response.data.results) {
159
160
  commit("SET_CATEGORIES", response.data.results);