@konfuzio/document-validation-ui 0.1.16-dev.0 → 0.1.16-dev.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.16-dev.0",
3
+ "version": "0.1.16-dev.2",
4
4
  "repository": "git://github.com:konfuzio-ai/document-validation-ui.git",
5
5
  "main": "dist/app.js",
6
6
  "scripts": {
@@ -53,7 +53,7 @@
53
53
  "@vue/test-utils": "^1.1.3",
54
54
  "@vue/vue2-jest": "^27.0.0",
55
55
  "babel-jest": "^27.0.6",
56
- "cypress": "^12.17.3",
56
+ "cypress": "^13.2.0",
57
57
  "dotenv": "^16.3.1",
58
58
  "eslint": "^8.30.0",
59
59
  "eslint-config-prettier": "^8.6.0",
@@ -1,6 +1,6 @@
1
1
  @import "./imports.scss";
2
2
 
3
- .document-top-bar-component {
3
+ #document-top-bar-component {
4
4
  width: 100%;
5
5
  height: $top-bar-height;
6
6
  border-bottom: $component-border;
@@ -35,11 +35,12 @@ describe("Document Annotations", () => {
35
35
  cy.mount(DocumentAnnotations);
36
36
  cy.get("#labels-sidebar")
37
37
  .find(".annotation-set-group")
38
- .then((elements) => {
39
- cy.storeState("document", "annotationSets")
40
- .its("length")
41
- .should("equal", elements.length);
42
- });
38
+ .then(($elements) => {
39
+ cy.getStore("document")
40
+ .then($document => {
41
+ expect($document.annotationSets).to.have.lengthOf($elements.length);
42
+ })
43
+ });
43
44
  });
44
45
 
45
46
  it("shows the empty state if there are no annotation sets", () => {
@@ -240,7 +241,7 @@ describe("Document Annotations", () => {
240
241
  .find(".empty-annotation")
241
242
  .find(".annotation-value")
242
243
  .not(".missing-annotation")
243
- .each(($annotation, index) => {
244
+ .each(($annotation) => {
244
245
  cy.wrap($annotation)
245
246
  .trigger("mouseover");
246
247
 
@@ -250,15 +251,26 @@ describe("Document Annotations", () => {
250
251
  .find(".action-buttons")
251
252
  .find(".missing-button-container")
252
253
  .find(".missing-btn")
253
- .click();
254
-
255
- cy.storeState("document", "missingAnnotations").its("length").should("not.eq", 0);
254
+ .click();
256
255
 
257
256
  cy.wrap($annotation)
258
257
  .trigger("mouseleave");
259
258
 
260
259
  cy.wait(1000);
261
- })
260
+ });
261
+
262
+ cy.get("#labels-sidebar")
263
+ .find(".label")
264
+ .find(".annotation-row")
265
+ .find(".empty-annotation")
266
+ .then($elements => {
267
+
268
+ cy.getStore("document")
269
+ .then($document => {
270
+ expect($document.missingAnnotations)
271
+ .to.have.lengthOf($elements.length);
272
+ });
273
+ })
262
274
  });
263
275
 
264
276
  it("restores empty annotation", () => {
@@ -34,7 +34,12 @@
34
34
  {{ $t("category") }}
35
35
  </p>
36
36
  <div class="category-name">
37
- {{ setCategoryDefaultText }}
37
+ <span>
38
+ {{ setCategoryDefaultText }}
39
+ </span>
40
+ <span v-if="splitMode && setCategoryConfidence >= 0">
41
+ {{ `(${setCategoryConfidence}%)` }}
42
+ </span>
38
43
  </div>
39
44
  </div>
40
45
  <div :class="[!splitMode && 'caret-section']">
@@ -48,13 +53,14 @@
48
53
  </template>
49
54
 
50
55
  <b-dropdown-item
51
- v-for="category in currentProjectCategories"
56
+ v-for="category in listOfCategories()"
52
57
  :key="category.id"
53
58
  aria-role="listitem"
54
59
  :disabled="handleOptionInDropdownDisabled(category)"
55
60
  @click="handleChangeCategory(category)"
56
61
  >
57
62
  <span>{{ category.name }}</span>
63
+ <span v-if="splitMode && category.confidence >= 0">{{ ` (${ category.confidence }%)` }}</span>
58
64
  </b-dropdown-item>
59
65
  </b-dropdown>
60
66
  </b-tooltip>
@@ -73,18 +79,17 @@ export default {
73
79
  splitMode: {
74
80
  type: Boolean,
75
81
  },
76
- page: {
77
- type: Object,
78
- default: null,
79
- },
80
- index: {
81
- type: Number,
82
- default: 0,
83
- },
82
+ page: {
83
+ type: Object,
84
+ default: null,
85
+ },
86
+ index: {
87
+ type: Number,
88
+ default: 0,
89
+ },
84
90
  },
85
91
  data() {
86
92
  return {
87
- currentProjectCategories: [],
88
93
  categoryError: false,
89
94
  tooltipIsShown: false,
90
95
  tooltipCloseDelay: 0,
@@ -139,21 +144,24 @@ export default {
139
144
  return categoryName ? categoryName : this.$t("choose_category");
140
145
  }
141
146
  },
147
+
148
+ setCategoryConfidence() {
149
+ if (!this.updatedDocument[this.index].categories || !this.categoryName(
150
+ this.updatedDocument[this.index].category
151
+ )) return;
152
+
153
+ const found = this.updatedDocument[this.index].categories.find(category => category.id === this.updatedDocument[this.index].category);
154
+
155
+ return this.handleCategoryConfidence(found.confidence);
156
+ }
142
157
  },
143
158
  watch: {
144
- categories() {
145
- this.handleCategories();
146
- },
147
159
  annotations() {
148
160
  this.checkIfDropdownIsDisabled();
149
161
  this.setTooltipText();
150
162
  },
151
163
  },
152
164
  mounted() {
153
- if (this.categories) {
154
- this.handleCategories();
155
- }
156
-
157
165
  if (this.projectHasSingleCategory()) {
158
166
  this.tooltipIsShown = true;
159
167
  }
@@ -163,16 +171,31 @@ export default {
163
171
  this.checkIfDropdownIsDisabled();
164
172
  },
165
173
  methods: {
166
- handleCategories() {
167
- this.categories.map((category) => {
168
- if (category.project === this.selectedDocument.project) {
169
- const found = this.currentProjectCategories.find(
170
- (cat) => cat.id === category.id
171
- );
172
- if (found) return;
173
- this.currentProjectCategories.push(category);
174
- }
175
- });
174
+ listOfCategories() {
175
+ let list;
176
+
177
+ if(this.splitMode && this.updatedDocument[this.index].categories) {
178
+ list = this.handleCategories(this.updatedDocument[this.index].categories);
179
+ } else if (this.categories) {
180
+ const filtered = this.categories.filter(category => category.project === this.selectedDocument.project)
181
+ list = this.handleCategories(filtered);
182
+ }
183
+
184
+ return list;
185
+ },
186
+ handleCategories(categories) {
187
+ return categories.map((category) => {
188
+ return {id: category.id, name: this.categoryName(category.id), confidence: this.handleCategoryConfidence(category.confidence)};
189
+ });
190
+ },
191
+ handleCategoryConfidence(confidence) {
192
+ if(!confidence) {
193
+ if(confidence === 0) return 0;
194
+
195
+ return;
196
+ }
197
+
198
+ return (confidence * 100).toFixed(2);
176
199
  },
177
200
  checkIfDropdownIsDisabled() {
178
201
  if (
@@ -193,7 +216,6 @@ export default {
193
216
 
194
217
  return category.id === this.updatedDocument[this.index].category;
195
218
  },
196
-
197
219
  handleChangeCategory(category) {
198
220
  // handling the category change will be different based on
199
221
  // the dropdown being on the topbar or the Rename and Categorize view
@@ -224,7 +246,6 @@ export default {
224
246
  // to update the new document category
225
247
  this.$emit("category-change", this.page, category.id);
226
248
  },
227
-
228
249
  setTooltipText() {
229
250
  // Text set from innerHTML vs 'label' due to html tag in locales file string
230
251
  let tooltipText;
@@ -114,6 +114,11 @@ export default {
114
114
 
115
115
  this.saveEditChanges();
116
116
  },
117
+ updatedDocument(newValue, oldValue) {
118
+ if(newValue && oldValue && newValue.length !== oldValue.length && newValue.length === 1) {
119
+ this.saveUpdatedDocuments();
120
+ }
121
+ }
117
122
  },
118
123
  mounted() {
119
124
  this.setPages();
@@ -287,6 +292,7 @@ export default {
287
292
  const newDocument = {
288
293
  name: this.handleNewDocumentName(i),
289
294
  category: this.handleNewDocumentCategory(i, clickedLines),
295
+ categories: this.handleNewDocumentCategoriesAndConfidence(i, clickedLines),
290
296
  pages: this.handleNewDocumentPages(i, clickedLines),
291
297
  };
292
298
 
@@ -309,7 +315,7 @@ export default {
309
315
  return newFileName;
310
316
  },
311
317
  handleNewDocumentCategory(index, clickedLines) {
312
- if (clickedLines[index].origin && clickedLines[index].origin === "AI") {
318
+ if (this.updatedDocument && this.updatedDocument.length > 1 && clickedLines[index].origin && clickedLines[index].origin === "AI") {
313
319
  // get the index of the new document in the splitting suggestions
314
320
  // to return its category
315
321
  const i = this.indexOfSplittingSuggestion(index, clickedLines);
@@ -319,6 +325,17 @@ export default {
319
325
  return this.selectedDocument.category;
320
326
  }
321
327
  },
328
+ handleNewDocumentCategoriesAndConfidence(index, clickedLines) {
329
+ if (this.updatedDocument && this.updatedDocument.length > 1 && clickedLines[index].origin && clickedLines[index].origin === "AI") {
330
+ // get the index of the new document in the splitting suggestions
331
+ // to return its category
332
+ const i = this.indexOfSplittingSuggestion(index, clickedLines);
333
+
334
+ return this.splittingSuggestions[i].categories;
335
+ } else {
336
+ return null;
337
+ }
338
+ },
322
339
  handleNewDocumentPages(index, clickedLines) {
323
340
  // assign the correct pages to each new document
324
341
  let pages;
@@ -380,8 +397,13 @@ export default {
380
397
  this.documentShouldBePostprocessed ||
381
398
  this.waitingForSplittingConfirmation(this.selectedDocument)
382
399
  ) {
400
+ // delete the document categories since the backend doesn't need them
401
+ const documentToProcess = this.updatedDocument.map(document => {
402
+ delete document.categories;
403
+ return document;
404
+ })
383
405
  this.$store
384
- .dispatch("edit/editDocument", this.updatedDocument)
406
+ .dispatch("edit/editDocument", documentToProcess)
385
407
  .catch((error) => {
386
408
  this.$store.dispatch("document/createErrorMessage", {
387
409
  error,
@@ -9,11 +9,12 @@ describe("Document Thumbnails", () => {
9
9
  cy.mount(DocumentThumbnails);
10
10
  cy.get("#document-pages")
11
11
  .find(".document-thumbnail")
12
- .then((elements) => {
13
- cy.storeState("document", "selectedDocument")
14
- .its("pages")
15
- .its("length")
16
- .should("equal", elements.length);
12
+ .then(($elements) => {
13
+ cy.getStore("document")
14
+ .then($document => {
15
+ expect($document.selectedDocument.pages)
16
+ .to.have.lengthOf($elements.length);
17
+ });
17
18
  });
18
19
  });
19
20
 
@@ -48,7 +49,12 @@ describe("Document Thumbnails", () => {
48
49
  .find(".document-thumbnail")
49
50
  .each(($row, index) => {
50
51
  cy.wrap($row).click();
51
- cy.storeState("display", "currentPage").should("equal", index + 1);
52
+ cy.getStore("display")
53
+ .then($display => {
54
+ expect($display.currentPage)
55
+ .to.equal(index + 1);
56
+ });
57
+
52
58
  cy.wait(1000);
53
59
  });
54
60
  });
@@ -0,0 +1,228 @@
1
+ import DocumentTopBar from "./DocumentTopBar";
2
+
3
+ describe("Document Top Bar", () => {
4
+ let currentDocument;
5
+ beforeEach(() => {
6
+
7
+ cy.fetchDocument().then(() => {
8
+ cy.getStore("document")
9
+ .then($document => {
10
+ currentDocument = $document.selectedDocument;
11
+ });
12
+
13
+
14
+ cy.getStore("project")
15
+ .then($project => {
16
+ cy.fetchCategories($project.projectId);
17
+ });
18
+ });
19
+
20
+ cy.dispatchAction("document", "setPublicView", false);
21
+ });
22
+
23
+ it("Shows category dropdown if not edit mode or reviewed", () => {
24
+ cy.mount(DocumentTopBar);
25
+
26
+ cy.get("#document-top-bar-component")
27
+ .find(".left-bar-components")
28
+ .find(".category-chooser")
29
+ .should("be.visible");
30
+ });
31
+
32
+ it("Shows correct file name", () => {
33
+ cy.mount(DocumentTopBar);
34
+ const fileName = currentDocument.data_file_name
35
+
36
+ cy.get("#document-top-bar-component")
37
+ .find(".center-bar-components")
38
+ .find(".document-name-component")
39
+ .should("be.visible");
40
+
41
+ cy.get("#document-top-bar-component")
42
+ .find(".center-bar-components")
43
+ .find(".document-name-component")
44
+ .find(".document-name")
45
+ .contains(fileName);
46
+ });
47
+
48
+ it("Shows arrows if available documents to navigate to", () => {
49
+ cy.mount(DocumentTopBar);
50
+ cy.fetchDocumentList();
51
+ const assignee = currentDocument.assignee;
52
+
53
+ cy.getStore("project")
54
+ .then($project => {
55
+ const filtered = $project.documentsInProject.filter(
56
+ (document) =>
57
+ (document.status_data === 41 || (document.status_data === 2 && document.labeling_available === 1)
58
+ ) && document.assignee === assignee
59
+ );
60
+
61
+ if(filtered.length > 0) {
62
+ cy.get("#document-top-bar-component")
63
+ .find(".center-bar-components")
64
+ .find(".navigation-arrow")
65
+ .should("be.visible");
66
+ }
67
+ });
68
+ });
69
+
70
+ it("Shows keyboard icon", () => {
71
+ cy.mount(DocumentTopBar);
72
+
73
+ cy.get("#document-top-bar-component")
74
+ .find(".right-bar-components")
75
+ .find(".keyboard-actions-info")
76
+ .should("be.visible");
77
+ });
78
+
79
+ it("Shows disabled finish review button", () => {
80
+ cy.mount(DocumentTopBar);
81
+
82
+ cy.get("#document-top-bar-component")
83
+ .find(".right-bar-components")
84
+ .find(".top-bar-buttons")
85
+ .find(".finish-review-button-container")
86
+ .should("be.visible");
87
+
88
+ cy.get("#document-top-bar-component")
89
+ .find(".right-bar-components")
90
+ .find(".top-bar-buttons")
91
+ .find(".finish-review-button-container")
92
+ .find(".finish-review-btn")
93
+ .should("be.disabled");
94
+ });
95
+
96
+ it("Shows edit mode buttons", () => {
97
+ cy.mount(DocumentTopBar);
98
+ cy.dispatchAction("edit", "enableEditMode");
99
+
100
+ cy.get("#document-top-bar-component")
101
+ .find(".right-bar-components")
102
+ .find(".top-bar-buttons")
103
+ .find(".finish-review-button-container")
104
+ .should("not.exist");
105
+
106
+ cy.get("#document-top-bar-component")
107
+ .find(".right-bar-components")
108
+ .find(".top-bar-buttons")
109
+ .find(".edit-mode-buttons")
110
+ .should("be.visible");
111
+
112
+ cy.dispatchAction("edit", "disableEditMode");
113
+ });
114
+
115
+ it("Edits file name", () => {
116
+ cy.mount(DocumentTopBar);
117
+ const fileName = currentDocument.data_file_name.split(".").slice(0, -1).join(".");
118
+
119
+ cy.get("#document-top-bar-component")
120
+ .find(".center-bar-components")
121
+ .find(".document-name-component")
122
+ .find(".edit-btn")
123
+ .click();
124
+
125
+ cy.get("#document-top-bar-component")
126
+ .find(".center-bar-components")
127
+ .find(".document-name-component")
128
+ .find(".document-name")
129
+ .should("have.class", "is-editable");
130
+
131
+ cy.get("#document-top-bar-component")
132
+ .find(".center-bar-components")
133
+ .find(".document-name-component")
134
+ .find(".document-name")
135
+ .type('{selectAll}')
136
+ .type('{backspace}')
137
+ .type("test-name");
138
+
139
+ cy.get("#document-top-bar-component")
140
+ .find(".center-bar-components")
141
+ .find(".document-name-component")
142
+ .find(".save-btn")
143
+ .should("be.visible");
144
+
145
+ cy.get("#document-top-bar-component")
146
+ .find(".center-bar-components")
147
+ .find(".document-name-component")
148
+ .find(".save-btn")
149
+ .click();
150
+
151
+ cy.wait(1000);
152
+
153
+ cy.get("#document-top-bar-component")
154
+ .find(".center-bar-components")
155
+ .find(".document-name-component")
156
+ .find(".cloud-icon")
157
+ .should("be.visible");
158
+
159
+ cy.wait(1000);
160
+
161
+ cy.get("#document-top-bar-component")
162
+ .find(".center-bar-components")
163
+ .find(".document-name-component")
164
+ .contains(fileName);
165
+ });
166
+
167
+ it("Shows tooltip when hovering over keyboard info", () => {
168
+ cy.mount(DocumentTopBar);
169
+
170
+ cy.get("#document-top-bar-component")
171
+ .find(".right-bar-components")
172
+ .find(".keyboard-actions-info")
173
+ .trigger("mouseenter");
174
+
175
+ cy.get("#document-top-bar-component")
176
+ .find(".right-bar-components")
177
+ .find(".keyboard-actions-info")
178
+ .find(".keyboard-actions-description")
179
+ .should("be.visible");
180
+
181
+ cy.get("#document-top-bar-component")
182
+ .find(".right-bar-components")
183
+ .find(".keyboard-actions-info")
184
+ .trigger("mouseleave");
185
+ });
186
+
187
+ it("Closes edit mode when clicking 'back to annotaiton view' button", () => {
188
+ cy.mount(DocumentTopBar);
189
+ cy.dispatchAction("edit", "enableEditMode");
190
+
191
+ cy.get("#document-top-bar-component")
192
+ .find(".right-bar-components")
193
+ .find(".edit-mode-buttons")
194
+ .should("exist");
195
+
196
+ cy.get("#document-top-bar-component")
197
+ .find(".right-bar-components")
198
+ .find(".edit-mode-buttons")
199
+ .find(".button-cancel")
200
+ .click();
201
+
202
+ cy.wait(1000);
203
+
204
+ cy.get("#document-top-bar-component")
205
+ .find(".right-bar-components")
206
+ .find(".edit-mode-buttons")
207
+ .should("not.exist");
208
+ });
209
+
210
+ it("Shows rename and categorize section when clicking 'next' button", () => {
211
+ cy.mount(DocumentTopBar);
212
+ cy.dispatchAction("edit", "enableEditMode");
213
+
214
+ cy.get("#document-top-bar-component")
215
+ .find(".right-bar-components")
216
+ .find(".edit-mode-buttons")
217
+ .find(".button-next")
218
+ .click();
219
+
220
+ cy.wait(1000);
221
+
222
+ cy.get("#document-top-bar-component")
223
+ .find(".right-bar-components")
224
+ .find(".edit-mode-buttons")
225
+ .find(".submit-btn")
226
+ .should("be.visible")
227
+ });
228
+ });
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div ref="documentTopBar" class="document-top-bar-component">
2
+ <div id="document-top-bar-component" ref="documentTopBar">
3
3
  <div
4
4
  v-if="selectedDocument && selectedDocument.pages.length > 0 && !loading"
5
5
  :class="['document-top-bar', editMode && 'edit-mode-top-bar']"
@@ -21,7 +21,7 @@
21
21
  <b-button
22
22
  :label="editMode && !renameAndCategorize ? $t('next') : $t('submit')"
23
23
  type="is-primary"
24
- class="button-next primary-button edit-mode-btn"
24
+ :class="['button-next primary-button edit-mode-btn', renameAndCategorize && 'submit-btn']"
25
25
  :disabled="renameAndCategorize && !enableSubmit"
26
26
  @click="handleButton"
27
27
  />