@konfuzio/document-validation-ui 0.1.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/.eslintrc.js +11 -0
- package/.prettierrc.json +1 -0
- package/LICENSE +21 -0
- package/README.md +13 -0
- package/dist/css/app.0c8973f8.css +1 -0
- package/dist/css/chunk-vendors.053b6b6e.css +5 -0
- package/dist/favicon.ico +0 -0
- package/dist/index.html +1 -0
- package/dist/js/app.17fe48c4.js +2 -0
- package/dist/js/app.17fe48c4.js.map +1 -0
- package/dist/js/chunk-vendors.a48fca3f.js +47 -0
- package/dist/js/chunk-vendors.a48fca3f.js.map +1 -0
- package/jest.config.js +4 -0
- package/package.json +60 -0
- package/src/.DS_Store +0 -0
- package/src/api.js +49 -0
- package/src/assets/images/AcceptedCheckMark.vue +8 -0
- package/src/assets/images/AcceptedUser.vue +8 -0
- package/src/assets/images/ActionIcon.vue +60 -0
- package/src/assets/images/ArrowDownKey.vue +11 -0
- package/src/assets/images/ArrowUpKey.vue +11 -0
- package/src/assets/images/CategoryIconImg.vue +13 -0
- package/src/assets/images/CheckMark.vue +8 -0
- package/src/assets/images/EditDocIcon.vue +12 -0
- package/src/assets/images/EmptyStateImg.vue +129 -0
- package/src/assets/images/ErrorIcon.vue +28 -0
- package/src/assets/images/EyeIcon.vue +11 -0
- package/src/assets/images/FileNameNotSavedImage.vue +26 -0
- package/src/assets/images/FileNameSavedImage.vue +14 -0
- package/src/assets/images/FitZoomIcon.vue +16 -0
- package/src/assets/images/KeyboardIcon.vue +16 -0
- package/src/assets/images/MinusIcon.vue +13 -0
- package/src/assets/images/NotOptimizedIllustration.vue +651 -0
- package/src/assets/images/PlusIcon.vue +13 -0
- package/src/assets/images/QuestionMark.vue +12 -0
- package/src/assets/images/ServerImage.vue +63 -0
- package/src/assets/images/SplitLines.vue +18 -0
- package/src/assets/images/SplitZigZag.vue +16 -0
- package/src/assets/images/StatusImg.vue +14 -0
- package/src/assets/images/UserIcon.vue +8 -0
- package/src/assets/scss/annotation_details.scss +126 -0
- package/src/assets/scss/categorize_modal.scss +42 -0
- package/src/assets/scss/choose_label_set_modal.scss +62 -0
- package/src/assets/scss/document_action_bar.scss +37 -0
- package/src/assets/scss/document_annotations.scss +472 -0
- package/src/assets/scss/document_category.scss +80 -0
- package/src/assets/scss/document_dashboard.scss +47 -0
- package/src/assets/scss/document_dataset_status.scss +46 -0
- package/src/assets/scss/document_edit.scss +431 -0
- package/src/assets/scss/document_error.scss +81 -0
- package/src/assets/scss/document_handover.scss +200 -0
- package/src/assets/scss/document_name.scss +62 -0
- package/src/assets/scss/document_page.scss +8 -0
- package/src/assets/scss/document_thumbnails.scss +41 -0
- package/src/assets/scss/document_toolbar.scss +89 -0
- package/src/assets/scss/document_top_bar.scss +139 -0
- package/src/assets/scss/document_viewport_modal.scss +25 -0
- package/src/assets/scss/documents_list.scss +130 -0
- package/src/assets/scss/empty_state.scss +34 -0
- package/src/assets/scss/extracting_data.scss +35 -0
- package/src/assets/scss/imports.scss +1 -0
- package/src/assets/scss/main.scss +24 -0
- package/src/assets/scss/multi_ann_table_popup.scss +12 -0
- package/src/assets/scss/new_annotation.scss +86 -0
- package/src/assets/scss/scrolling_document.scss +19 -0
- package/src/assets/scss/variables.scss +696 -0
- package/src/components/App.vue +112 -0
- package/src/components/DocumentAnnotations/ActionButtons.vue +237 -0
- package/src/components/DocumentAnnotations/AnnotationContent.vue +249 -0
- package/src/components/DocumentAnnotations/AnnotationDetails.vue +292 -0
- package/src/components/DocumentAnnotations/AnnotationRow.vue +616 -0
- package/src/components/DocumentAnnotations/CategorizeModal.vue +159 -0
- package/src/components/DocumentAnnotations/ChooseLabelSetModal.vue +155 -0
- package/src/components/DocumentAnnotations/DocumentAnnotations.vue +502 -0
- package/src/components/DocumentAnnotations/DocumentLabel.vue +148 -0
- package/src/components/DocumentAnnotations/EmptyAnnotation.vue +222 -0
- package/src/components/DocumentAnnotations/EmptyState.vue +21 -0
- package/src/components/DocumentAnnotations/ExtractingData.vue +29 -0
- package/src/components/DocumentAnnotations/LoadingAnnotations.vue +43 -0
- package/src/components/DocumentAnnotations/LoadingLabels.vue +43 -0
- package/src/components/DocumentAnnotations/RejectedLabels.vue +96 -0
- package/src/components/DocumentAnnotations/index.js +8 -0
- package/src/components/DocumentCategory.vue +156 -0
- package/src/components/DocumentDashboard.vue +159 -0
- package/src/components/DocumentEdit/DocumentEdit.vue +279 -0
- package/src/components/DocumentEdit/EditPages.vue +213 -0
- package/src/components/DocumentEdit/EditSidebar.vue +118 -0
- package/src/components/DocumentEdit/SplitOverview.vue +182 -0
- package/src/components/DocumentEdit/index.js +4 -0
- package/src/components/DocumentError.vue +53 -0
- package/src/components/DocumentPage/ActionBar.vue +48 -0
- package/src/components/DocumentPage/BoxSelection.vue +149 -0
- package/src/components/DocumentPage/DocumentPage.vue +517 -0
- package/src/components/DocumentPage/DocumentToolbar.vue +145 -0
- package/src/components/DocumentPage/DummyPage.vue +53 -0
- package/src/components/DocumentPage/MultiAnnSelection.vue +302 -0
- package/src/components/DocumentPage/MultiAnnotationTablePopup.vue +253 -0
- package/src/components/DocumentPage/NewAnnotation.vue +283 -0
- package/src/components/DocumentPage/ScrollingDocument.vue +108 -0
- package/src/components/DocumentPage/ScrollingPage.vue +184 -0
- package/src/components/DocumentPage/index.js +5 -0
- package/src/components/DocumentThumbnails/DocumentThumbnails.vue +92 -0
- package/src/components/DocumentThumbnails/LoadingThumbnail.vue +25 -0
- package/src/components/DocumentThumbnails/index.js +1 -0
- package/src/components/DocumentTopBar/DocumentDatasetStatus.vue +103 -0
- package/src/components/DocumentTopBar/DocumentHandover.vue +202 -0
- package/src/components/DocumentTopBar/DocumentName.vue +224 -0
- package/src/components/DocumentTopBar/DocumentTopBar.vue +144 -0
- package/src/components/DocumentTopBar/DocumentTopBarButtons.vue +148 -0
- package/src/components/DocumentTopBar/KeyboardActionsDescription.vue +71 -0
- package/src/components/DocumentTopBar/index.js +5 -0
- package/src/components/DocumentsList/DocumentsList.vue +126 -0
- package/src/components/DocumentsList/index.js +1 -0
- package/src/components/ErrorMessage.vue +40 -0
- package/src/components/NotOptimizedViewportModal.vue +54 -0
- package/src/constants.js +4 -0
- package/src/directives/scroll.js +28 -0
- package/src/i18n.js +23 -0
- package/src/locales/de.json +114 -0
- package/src/locales/en.json +114 -0
- package/src/locales/es.json +113 -0
- package/src/main.js +87 -0
- package/src/store/category.js +193 -0
- package/src/store/display.js +238 -0
- package/src/store/document.js +1057 -0
- package/src/store/edit.js +210 -0
- package/src/store/index.js +22 -0
- package/src/store/project.js +95 -0
- package/src/store/selection.js +179 -0
- package/src/utils/utils.js +3 -0
- package/vue.config.js +13 -0
|
@@ -0,0 +1,1057 @@
|
|
|
1
|
+
import myImports from "../api";
|
|
2
|
+
import sleep from "../utils/utils";
|
|
3
|
+
|
|
4
|
+
const HTTP = myImports.HTTP;
|
|
5
|
+
const documentPollDuration = 1000;
|
|
6
|
+
|
|
7
|
+
const state = {
|
|
8
|
+
loading: true,
|
|
9
|
+
pages: [],
|
|
10
|
+
annotationSets: null,
|
|
11
|
+
annotations: null,
|
|
12
|
+
labels: [],
|
|
13
|
+
documentId: null,
|
|
14
|
+
sidebarAnnotationSelected: null,
|
|
15
|
+
documentAnnotationSelected: null,
|
|
16
|
+
selectedDocument: null,
|
|
17
|
+
recalculatingAnnotations: false,
|
|
18
|
+
editAnnotation: null,
|
|
19
|
+
missingAnnotations: [],
|
|
20
|
+
publicView: true,
|
|
21
|
+
showActionError: false,
|
|
22
|
+
errorMessage: null,
|
|
23
|
+
showDocumentError: false,
|
|
24
|
+
rejectedMissingAnnotations: null,
|
|
25
|
+
errorMessageWidth: null,
|
|
26
|
+
hoveredAnnotationSet: null,
|
|
27
|
+
finishedReview: false,
|
|
28
|
+
newAcceptedAnnotations: null,
|
|
29
|
+
selectedEntities: null,
|
|
30
|
+
serverError: false,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const getters = {
|
|
34
|
+
/**
|
|
35
|
+
* Get entities inside a box
|
|
36
|
+
*/
|
|
37
|
+
entitiesOnSelection: (state) => (box, page) => {
|
|
38
|
+
return page.entities.filter(
|
|
39
|
+
(entity) =>
|
|
40
|
+
box.x0 <= entity.x0 &&
|
|
41
|
+
box.x1 >= entity.x1 &&
|
|
42
|
+
box.y0 <= entity.y0 &&
|
|
43
|
+
box.y1 >= entity.y1
|
|
44
|
+
);
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Number of pages. If the pages array doesn't exist yet, return 0.
|
|
49
|
+
*/
|
|
50
|
+
pageCount: (state) => {
|
|
51
|
+
if (state.selectedDocument.pages) {
|
|
52
|
+
return state.selectedDocument.pages.length;
|
|
53
|
+
}
|
|
54
|
+
return 0;
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Returns the current page
|
|
59
|
+
*/
|
|
60
|
+
pageSelected: (state, _, rootState) => {
|
|
61
|
+
if (state.pages) {
|
|
62
|
+
return state.pages[rootState.display.currentPage - 1];
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Returns a page in the given index
|
|
69
|
+
*/
|
|
70
|
+
pageAtIndex: (state) => (index) => {
|
|
71
|
+
if (state.selectedDocument && state.selectedDocument.pages) {
|
|
72
|
+
return state.selectedDocument.pages[index];
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Checks if is to scroll to an annotation in the document
|
|
79
|
+
*/
|
|
80
|
+
scrollDocumentToAnnotation: (state) => {
|
|
81
|
+
return (
|
|
82
|
+
state.documentAnnotationSelected &&
|
|
83
|
+
state.documentAnnotationSelected.scrollTo
|
|
84
|
+
);
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Checks if the document is categorized and ready to start the review
|
|
89
|
+
*/
|
|
90
|
+
categorizationIsConfirmed: (state) => {
|
|
91
|
+
if (state.selectedDocument) {
|
|
92
|
+
if (
|
|
93
|
+
state.selectedDocument.category_is_revised ||
|
|
94
|
+
state.selectedDocument.is_reviewed
|
|
95
|
+
) {
|
|
96
|
+
return true;
|
|
97
|
+
} else if (!state.selectedDocument.category) {
|
|
98
|
+
return false;
|
|
99
|
+
} else {
|
|
100
|
+
// check if there's any annotation already approved
|
|
101
|
+
const found = state.annotations.find((annotation) => {
|
|
102
|
+
return annotation.revised;
|
|
103
|
+
});
|
|
104
|
+
return found != undefined;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Gets labels for an annotation creation from a label/annotation set
|
|
112
|
+
*/
|
|
113
|
+
labelsFilteredForAnnotationCreation: (state) => (set) => {
|
|
114
|
+
let returnLabels = [];
|
|
115
|
+
if (set.id && set.labels) {
|
|
116
|
+
// if existing ann set, check for multiple
|
|
117
|
+
returnLabels = set.labels.filter((label) => {
|
|
118
|
+
// check if label has multiple and if not, if there's already an annotation created
|
|
119
|
+
if (!label.has_multiple_top_candidates) {
|
|
120
|
+
const existingLabel = state.labels.find((documentLabel) => {
|
|
121
|
+
return documentLabel.id === label.id;
|
|
122
|
+
});
|
|
123
|
+
return (
|
|
124
|
+
existingLabel &&
|
|
125
|
+
existingLabel.annotations &&
|
|
126
|
+
existingLabel.annotations.length === 0
|
|
127
|
+
);
|
|
128
|
+
} else {
|
|
129
|
+
return true;
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
} else if (set.labels) {
|
|
133
|
+
// if not existing ann set, then return all labels
|
|
134
|
+
returnLabels = set.labels;
|
|
135
|
+
}
|
|
136
|
+
return returnLabels;
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
/* Checks if annotation is in deleted state */
|
|
140
|
+
isAnnotationDeleted: (state) => (annotation) => {
|
|
141
|
+
if (annotation) {
|
|
142
|
+
return annotation.revised && !annotation.is_correct;
|
|
143
|
+
}
|
|
144
|
+
return false;
|
|
145
|
+
},
|
|
146
|
+
|
|
147
|
+
/* Checks if the label has annotations to show */
|
|
148
|
+
labelHasAnnotations: (_, getters) => (label) => {
|
|
149
|
+
const annotations = label.annotations.filter((annotation) => {
|
|
150
|
+
return !getters.isAnnotationDeleted(annotation);
|
|
151
|
+
});
|
|
152
|
+
return annotations.length > 0;
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
/* Checks if the document has an annotation set */
|
|
156
|
+
annotationSetExists: (state) => (annotationSetId) => {
|
|
157
|
+
return state.annotationSets.find((annSet) => annSet.id === annotationSetId);
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
/* Process annotations and extract labels and sets */
|
|
161
|
+
processAnnotationSets: (state, getters) => (annotationSets) => {
|
|
162
|
+
// group annotations for sidebar
|
|
163
|
+
const annotations = [];
|
|
164
|
+
const labels = [];
|
|
165
|
+
const processedAnnotationSets = annotationSets.map((annotationSet) => {
|
|
166
|
+
const annotationSetLabels = annotationSet.labels.map((label) => {
|
|
167
|
+
// filter label
|
|
168
|
+
const filteredLabel = getters.annotationsInLabelFiltered(label);
|
|
169
|
+
|
|
170
|
+
// add annotations to the document array
|
|
171
|
+
annotations.push(...filteredLabel.annotations);
|
|
172
|
+
labels.push(filteredLabel);
|
|
173
|
+
// add labels to the labels array
|
|
174
|
+
return filteredLabel;
|
|
175
|
+
});
|
|
176
|
+
annotationSet.labels = annotationSetLabels;
|
|
177
|
+
return annotationSet;
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
annotationSets: processedAnnotationSets,
|
|
182
|
+
labels,
|
|
183
|
+
annotations,
|
|
184
|
+
};
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
/* Returns the number of accepted annotations in a label */
|
|
188
|
+
numberOfAcceptedAnnotationsInLabel: (_) => (label) => {
|
|
189
|
+
const annotations = label.annotations.filter((annotation) => {
|
|
190
|
+
return annotation.revised && annotation.is_correct;
|
|
191
|
+
});
|
|
192
|
+
return annotations.length;
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Checks if theres a group of annotation sets and add an index number to them
|
|
197
|
+
*/
|
|
198
|
+
numberOfAnnotationSetGroup: (state) => (annotationSet) => {
|
|
199
|
+
let found = false;
|
|
200
|
+
let value = 0;
|
|
201
|
+
let index = 0;
|
|
202
|
+
if (state.annotationSets) {
|
|
203
|
+
state.annotationSets.map((annotationSetTemp) => {
|
|
204
|
+
if (
|
|
205
|
+
annotationSetTemp.id !== annotationSet.id &&
|
|
206
|
+
annotationSetTemp.label_set.id === annotationSet.label_set.id &&
|
|
207
|
+
annotationSetTemp.label_set.name === annotationSet.label_set.name
|
|
208
|
+
) {
|
|
209
|
+
found = true;
|
|
210
|
+
index++;
|
|
211
|
+
} else if (
|
|
212
|
+
annotationSetTemp.label_set.id === annotationSet.label_set.id
|
|
213
|
+
) {
|
|
214
|
+
value = index;
|
|
215
|
+
}
|
|
216
|
+
});
|
|
217
|
+
return found ? `${value + 1}` : "";
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Get label with annotations filtered if the label supports multiple or not
|
|
223
|
+
*/
|
|
224
|
+
annotationsInLabelFiltered: (state) => (label) => {
|
|
225
|
+
let labelToReturn;
|
|
226
|
+
if (
|
|
227
|
+
label.has_multiple_top_candidates === false &&
|
|
228
|
+
label.annotations &&
|
|
229
|
+
label.annotations.length > 1
|
|
230
|
+
) {
|
|
231
|
+
let highestConfidenceAnnotation = label.annotations[0];
|
|
232
|
+
for (let i = 1; i < label.annotations.length; i++) {
|
|
233
|
+
// check which one has more confidence or if it's the same, then check if one is revised or not
|
|
234
|
+
if (
|
|
235
|
+
highestConfidenceAnnotation.confidence <
|
|
236
|
+
label.annotations[i].confidence ||
|
|
237
|
+
(highestConfidenceAnnotation.confidence ===
|
|
238
|
+
label.annotations[i].confidence &&
|
|
239
|
+
label.annotations[i].revised)
|
|
240
|
+
) {
|
|
241
|
+
highestConfidenceAnnotation = label.annotations[i];
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
labelToReturn = {
|
|
245
|
+
...label,
|
|
246
|
+
annotations: [highestConfidenceAnnotation],
|
|
247
|
+
};
|
|
248
|
+
} else {
|
|
249
|
+
labelToReturn = {
|
|
250
|
+
...label,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
return labelToReturn;
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Checks if annotation is being edited
|
|
258
|
+
*/
|
|
259
|
+
isAnnotationInEditMode:
|
|
260
|
+
(state) =>
|
|
261
|
+
(annotationId, index = null) => {
|
|
262
|
+
if (state.editAnnotation && annotationId) {
|
|
263
|
+
if (index != null) {
|
|
264
|
+
return (
|
|
265
|
+
state.editAnnotation.id === annotationId &&
|
|
266
|
+
state.editAnnotation.index === index
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
return state.editAnnotation.id === annotationId;
|
|
270
|
+
}
|
|
271
|
+
},
|
|
272
|
+
|
|
273
|
+
/**
|
|
274
|
+
* Get number of empty labels per annotation set
|
|
275
|
+
*/
|
|
276
|
+
emptyLabelsLength: (state) => (annotationSet) => {
|
|
277
|
+
const labels = annotationSet.labels.filter(
|
|
278
|
+
(label) => label.annotations.length === 0
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
const pendingEmpty = [];
|
|
282
|
+
|
|
283
|
+
labels.map((label) => {
|
|
284
|
+
const found = state.missingAnnotations.find(
|
|
285
|
+
(l) => l.label === label.id && annotationSet.id === l.annotation_set
|
|
286
|
+
);
|
|
287
|
+
|
|
288
|
+
if (!found) {
|
|
289
|
+
pendingEmpty.push(label);
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
return pendingEmpty.length;
|
|
294
|
+
},
|
|
295
|
+
|
|
296
|
+
// Check if document is ready to be finished
|
|
297
|
+
isDocumentReviewFinished: (state) => () => {
|
|
298
|
+
// check if all annotations have been revised
|
|
299
|
+
let notRevised;
|
|
300
|
+
|
|
301
|
+
const emptyAnnotations = [];
|
|
302
|
+
|
|
303
|
+
if (state.annotationSets) {
|
|
304
|
+
state.annotationSets.forEach((annSet) => {
|
|
305
|
+
annSet.labels.map((label) => {
|
|
306
|
+
// return only labels with empty annotations
|
|
307
|
+
if (label.annotations.length === 0) {
|
|
308
|
+
emptyAnnotations.push({
|
|
309
|
+
label: label.id,
|
|
310
|
+
label_set: annSet.label_set.id,
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
if (state.annotations) {
|
|
318
|
+
notRevised = state.annotations.filter((a) => !a.revised);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// if all annotations have been revised
|
|
322
|
+
// and if there are no empty annotations or
|
|
323
|
+
// all empty annotations were rejected,
|
|
324
|
+
// we can finish the review
|
|
325
|
+
if (
|
|
326
|
+
!emptyAnnotations ||
|
|
327
|
+
!state.missingAnnotations ||
|
|
328
|
+
!notRevised ||
|
|
329
|
+
(notRevised.length === 0 &&
|
|
330
|
+
state.missingAnnotations.length === emptyAnnotations.length)
|
|
331
|
+
) {
|
|
332
|
+
return true;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return false;
|
|
336
|
+
},
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Get number of annotations pending review per annotation set
|
|
340
|
+
*/
|
|
341
|
+
annotationsWithPendingReviewLength: () => (annotationSet) => {
|
|
342
|
+
const labels = annotationSet.labels.filter(
|
|
343
|
+
(label) => label.annotations.length > 0
|
|
344
|
+
);
|
|
345
|
+
|
|
346
|
+
const annotationsWithPendingReview = [];
|
|
347
|
+
|
|
348
|
+
labels.map((label) => {
|
|
349
|
+
const foundPendingAnnotation = label.annotations.find(
|
|
350
|
+
(ann) => !ann.revised
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
if (foundPendingAnnotation) {
|
|
354
|
+
annotationsWithPendingReview.push(foundPendingAnnotation);
|
|
355
|
+
}
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
// Check if we have grouped annotations by same label
|
|
359
|
+
if (state.enableGroupingFeature && label.annotations.length < 2) {
|
|
360
|
+
return annotationsWithPendingReview.length - label.annotations.length;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
return annotationsWithPendingReview.length;
|
|
364
|
+
},
|
|
365
|
+
|
|
366
|
+
/**
|
|
367
|
+
* Check if the document was extracted correctly and is ready to be reviewed
|
|
368
|
+
*/
|
|
369
|
+
isDocumentReadyToBeReviewed: () => (document) => {
|
|
370
|
+
return document.status_data === 2 && document.labeling_available === 1;
|
|
371
|
+
},
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Check if the document had an error during extraction
|
|
375
|
+
*/
|
|
376
|
+
documentHadErrorDuringExtraction: () => (document) => {
|
|
377
|
+
return document.status_data === 111;
|
|
378
|
+
},
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* check if the document has a dataset status of 'Training', 'Test' or 'Preparation'
|
|
382
|
+
* or if it is Ready Only / Reviewed
|
|
383
|
+
* and if so disable the option to edit the document
|
|
384
|
+
*/
|
|
385
|
+
documentCannotBeEdited: (state) => (document) => {
|
|
386
|
+
return (
|
|
387
|
+
document.dataset_status === 1 ||
|
|
388
|
+
document.dataset_status === 2 ||
|
|
389
|
+
document.dataset_status === 3 ||
|
|
390
|
+
document.is_reviewed ||
|
|
391
|
+
state.publicView
|
|
392
|
+
);
|
|
393
|
+
},
|
|
394
|
+
|
|
395
|
+
getTextFromEntities: (state) => () => {
|
|
396
|
+
return state.selectedEntities
|
|
397
|
+
.map((entity) => {
|
|
398
|
+
return entity.content;
|
|
399
|
+
})
|
|
400
|
+
.join(" ");
|
|
401
|
+
},
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
const actions = {
|
|
405
|
+
startLoading: ({ commit }) => {
|
|
406
|
+
commit("SET_LOADING", true);
|
|
407
|
+
},
|
|
408
|
+
endLoading: ({ commit }) => {
|
|
409
|
+
commit("SET_LOADING", false);
|
|
410
|
+
},
|
|
411
|
+
setDocId: ({ commit }, id) => {
|
|
412
|
+
commit("SET_PAGES", []);
|
|
413
|
+
commit("SET_DOC_ID", id);
|
|
414
|
+
},
|
|
415
|
+
setSidebarAnnotationSelected: ({ commit }, annotation) => {
|
|
416
|
+
commit("SET_ANNOTATION_SELECTED", annotation);
|
|
417
|
+
},
|
|
418
|
+
setAnnotationSets: ({ commit }, annotationSets) => {
|
|
419
|
+
commit("SET_ANNOTATION_SETS", annotationSets);
|
|
420
|
+
},
|
|
421
|
+
setEditAnnotation: (
|
|
422
|
+
{ commit },
|
|
423
|
+
{ id, index, label, labelSet, annotationSet }
|
|
424
|
+
) => {
|
|
425
|
+
const value = {
|
|
426
|
+
id,
|
|
427
|
+
index,
|
|
428
|
+
label,
|
|
429
|
+
labelSet,
|
|
430
|
+
annotationSet,
|
|
431
|
+
};
|
|
432
|
+
commit("SET_EDIT_ANNOTATION", value);
|
|
433
|
+
},
|
|
434
|
+
resetEditAnnotation: ({ commit }) => {
|
|
435
|
+
commit("RESET_EDIT_ANNOTATION");
|
|
436
|
+
},
|
|
437
|
+
setAnnotations: ({ commit }, annotations) => {
|
|
438
|
+
commit("SET_ANNOTATIONS", annotations);
|
|
439
|
+
},
|
|
440
|
+
setLabels: ({ commit }, labels) => {
|
|
441
|
+
commit("SET_LABELS", labels);
|
|
442
|
+
},
|
|
443
|
+
setPages: ({ commit }, pages) => {
|
|
444
|
+
commit("SET_PAGES", pages);
|
|
445
|
+
},
|
|
446
|
+
setSelectedDocument: ({ commit }, document) => {
|
|
447
|
+
commit("SET_SELECTED_DOCUMENT", document);
|
|
448
|
+
},
|
|
449
|
+
setPublicView: ({ commit }, publicView) => {
|
|
450
|
+
commit("SET_PUBLIC_VIEW", publicView);
|
|
451
|
+
},
|
|
452
|
+
startRecalculatingAnnotations: ({ commit }) => {
|
|
453
|
+
commit("SET_RECALCULATING_ANNOTATIONS", true);
|
|
454
|
+
},
|
|
455
|
+
endRecalculatingAnnotations: ({ commit }) => {
|
|
456
|
+
commit("SET_RECALCULATING_ANNOTATIONS", false);
|
|
457
|
+
},
|
|
458
|
+
setMissingAnnotations: ({ commit }, missingAnnotations) => {
|
|
459
|
+
commit("SET_MISSING_ANNOTATIONS", missingAnnotations);
|
|
460
|
+
},
|
|
461
|
+
setErrorMessage: ({ commit, dispatch }, message) => {
|
|
462
|
+
if (message) {
|
|
463
|
+
commit("SET_SHOW_ACTION_ERROR", true);
|
|
464
|
+
} else {
|
|
465
|
+
commit("SET_SHOW_ACTION_ERROR", false);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
commit("SET_ERROR_MESSAGE", message);
|
|
469
|
+
|
|
470
|
+
dispatch("closeErrorMessage");
|
|
471
|
+
},
|
|
472
|
+
setDocumentError: ({ commit }, value) => {
|
|
473
|
+
commit("SET_DOCUMENT_ERROR", value);
|
|
474
|
+
},
|
|
475
|
+
setRejectedMissingAnnotations: ({ commit }, annotations) => {
|
|
476
|
+
commit("SET_REJECTED_MISSING_ANNOTATIONS", annotations);
|
|
477
|
+
},
|
|
478
|
+
setErrorMessageWidth: ({ commit }, width) => {
|
|
479
|
+
commit("SET_ERROR_MESSAGE_WIDTH", width);
|
|
480
|
+
},
|
|
481
|
+
setHoveredAnnotationSet: ({ commit }, annotationSet) => {
|
|
482
|
+
commit("SET_HOVERED_ANNOTATION_SET", annotationSet);
|
|
483
|
+
},
|
|
484
|
+
setNewAcceptedAnnotations: ({ commit }, annotations) => {
|
|
485
|
+
commit("SET_NEW_ACCEPTED_ANNOTATIONS", annotations);
|
|
486
|
+
},
|
|
487
|
+
setSelectedEntities: ({ commit }, entities) => {
|
|
488
|
+
commit("SET_SELECTED_ENTITIES", entities);
|
|
489
|
+
},
|
|
490
|
+
|
|
491
|
+
/**
|
|
492
|
+
* Actions that use HTTP requests always return the axios promise,
|
|
493
|
+
* so they can be `await`ed (useful to set the `loading` status).
|
|
494
|
+
*/
|
|
495
|
+
fetchDocument: async (
|
|
496
|
+
{ commit, state, dispatch, rootState, getters },
|
|
497
|
+
pollDocumentList = false
|
|
498
|
+
) => {
|
|
499
|
+
let projectId = null;
|
|
500
|
+
let categoryId = null;
|
|
501
|
+
let isRecalculatingAnnotations = false;
|
|
502
|
+
|
|
503
|
+
const initialPage = 1;
|
|
504
|
+
|
|
505
|
+
dispatch("startLoading");
|
|
506
|
+
dispatch("display/updateCurrentPage", initialPage, {
|
|
507
|
+
root: true,
|
|
508
|
+
});
|
|
509
|
+
|
|
510
|
+
await HTTP.get(`documents/${state.documentId}/`)
|
|
511
|
+
.then(async (response) => {
|
|
512
|
+
if (response.data) {
|
|
513
|
+
const { labels, annotations, annotationSets } =
|
|
514
|
+
getters.processAnnotationSets(response.data.annotation_sets);
|
|
515
|
+
|
|
516
|
+
// load first page
|
|
517
|
+
if (response.data.pages.length > 0) {
|
|
518
|
+
await dispatch("fetchDocumentPage", initialPage);
|
|
519
|
+
}
|
|
520
|
+
// set information on the store
|
|
521
|
+
commit("SET_ANNOTATION_SETS", annotationSets);
|
|
522
|
+
commit("SET_ANNOTATIONS", annotations);
|
|
523
|
+
commit("SET_LABELS", labels);
|
|
524
|
+
commit("SET_SELECTED_DOCUMENT", response.data);
|
|
525
|
+
commit("SET_FINISHED_REVIEW", getters.isDocumentReviewFinished());
|
|
526
|
+
|
|
527
|
+
if (rootState.project.projectId) {
|
|
528
|
+
projectId = rootState.project.projectId;
|
|
529
|
+
} else {
|
|
530
|
+
projectId = response.data.project;
|
|
531
|
+
dispatch("project/setProjectId", response.data.project, {
|
|
532
|
+
root: true,
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
categoryId = response.data.category;
|
|
537
|
+
// TODO: add this validation to a method
|
|
538
|
+
isRecalculatingAnnotations = response.data.labeling_available !== 1;
|
|
539
|
+
}
|
|
540
|
+
})
|
|
541
|
+
.catch((error) => {
|
|
542
|
+
console.log(error, "Could not fetch document details from the backend");
|
|
543
|
+
return;
|
|
544
|
+
});
|
|
545
|
+
|
|
546
|
+
await dispatch("fetchMissingAnnotations");
|
|
547
|
+
|
|
548
|
+
if (!state.publicView) {
|
|
549
|
+
await dispatch("project/fetchCurrentUser", null, {
|
|
550
|
+
root: true,
|
|
551
|
+
});
|
|
552
|
+
|
|
553
|
+
if (projectId) {
|
|
554
|
+
await dispatch("category/fetchCategories", projectId, {
|
|
555
|
+
root: true,
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
if (categoryId) {
|
|
559
|
+
await dispatch(
|
|
560
|
+
"category/createAvailableDocumentsList",
|
|
561
|
+
{
|
|
562
|
+
categoryId,
|
|
563
|
+
user: rootState.project.currentUser,
|
|
564
|
+
poll: pollDocumentList,
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
root: true,
|
|
568
|
+
}
|
|
569
|
+
);
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
if (isRecalculatingAnnotations) {
|
|
573
|
+
commit("SET_RECALCULATING_ANNOTATIONS", true);
|
|
574
|
+
dispatch("pollDocumentEndpoint");
|
|
575
|
+
}
|
|
576
|
+
dispatch("endLoading");
|
|
577
|
+
},
|
|
578
|
+
|
|
579
|
+
// Get document page data
|
|
580
|
+
fetchDocumentPage: ({ commit, state }, page) => {
|
|
581
|
+
return HTTP.get(`documents/${state.documentId}/pages/${page}/`)
|
|
582
|
+
.then((response) => {
|
|
583
|
+
commit("ADD_PAGE", response.data);
|
|
584
|
+
})
|
|
585
|
+
.catch((error) => {
|
|
586
|
+
console.log(error);
|
|
587
|
+
});
|
|
588
|
+
},
|
|
589
|
+
|
|
590
|
+
setDocumentAnnotationSelected: (
|
|
591
|
+
{ commit },
|
|
592
|
+
{ annotation, label, span, scrollTo = false }
|
|
593
|
+
) => {
|
|
594
|
+
const value = {
|
|
595
|
+
scrollTo,
|
|
596
|
+
id: annotation.id,
|
|
597
|
+
span,
|
|
598
|
+
page: span.page_index + 1,
|
|
599
|
+
labelName: label.name,
|
|
600
|
+
};
|
|
601
|
+
commit("SET_DOCUMENT_ANNOTATION_SELECTED", value);
|
|
602
|
+
},
|
|
603
|
+
|
|
604
|
+
scrollToDocumentAnnotationSelected: ({ commit }) => {
|
|
605
|
+
commit("SET_DOCUMENT_ANNOTATION_SCROLL", true);
|
|
606
|
+
},
|
|
607
|
+
|
|
608
|
+
disableDocumentAnnotationSelected: ({ commit }) => {
|
|
609
|
+
commit("SET_DOCUMENT_ANNOTATION_SELECTED", null);
|
|
610
|
+
},
|
|
611
|
+
|
|
612
|
+
createAnnotation: ({ commit, getters, dispatch }, annotation) => {
|
|
613
|
+
return new Promise((resolve, reject) => {
|
|
614
|
+
HTTP.post(`/annotations/`, annotation)
|
|
615
|
+
.then(async (response) => {
|
|
616
|
+
if (response.status === 201) {
|
|
617
|
+
dispatch("fetchMissingAnnotations");
|
|
618
|
+
commit("SET_FINISHED_REVIEW", getters.isDocumentReviewFinished());
|
|
619
|
+
|
|
620
|
+
if (!getters.annotationSetExists(response.data.annotation_set)) {
|
|
621
|
+
const documentData = await dispatch("fetchDocumentData");
|
|
622
|
+
if (documentData && documentData.annotation_sets) {
|
|
623
|
+
const { labels, annotations, annotationSets } =
|
|
624
|
+
getters.processAnnotationSets(documentData.annotation_sets);
|
|
625
|
+
commit("SET_ANNOTATION_SETS", annotationSets);
|
|
626
|
+
commit("SET_ANNOTATIONS", annotations);
|
|
627
|
+
commit("SET_LABELS", labels);
|
|
628
|
+
}
|
|
629
|
+
} else {
|
|
630
|
+
commit("ADD_ANNOTATION", response.data);
|
|
631
|
+
}
|
|
632
|
+
resolve(response);
|
|
633
|
+
}
|
|
634
|
+
})
|
|
635
|
+
.catch((error) => {
|
|
636
|
+
reject(error.response);
|
|
637
|
+
console.log(error);
|
|
638
|
+
});
|
|
639
|
+
});
|
|
640
|
+
},
|
|
641
|
+
|
|
642
|
+
updateAnnotation: ({ commit, getters }, { updatedValues, annotationId }) => {
|
|
643
|
+
commit("SET_NEW_ACCEPTED_ANNOTATIONS", [annotationId]);
|
|
644
|
+
|
|
645
|
+
return new Promise((resolve, reject) => {
|
|
646
|
+
HTTP.patch(`/annotations/${annotationId}/`, updatedValues)
|
|
647
|
+
.then((response) => {
|
|
648
|
+
if (response.status === 200) {
|
|
649
|
+
commit("UPDATE_ANNOTATION", response.data);
|
|
650
|
+
commit("SET_FINISHED_REVIEW", getters.isDocumentReviewFinished());
|
|
651
|
+
commit("SET_NEW_ACCEPTED_ANNOTATIONS", null);
|
|
652
|
+
resolve(true);
|
|
653
|
+
}
|
|
654
|
+
})
|
|
655
|
+
.catch((error) => {
|
|
656
|
+
reject(error.response);
|
|
657
|
+
console.log(error);
|
|
658
|
+
});
|
|
659
|
+
});
|
|
660
|
+
},
|
|
661
|
+
|
|
662
|
+
deleteAnnotation: ({ commit, getters }, { annotationId }) => {
|
|
663
|
+
return new Promise((resolve, reject) => {
|
|
664
|
+
HTTP.delete(`/annotations/${annotationId}/`)
|
|
665
|
+
.then((response) => {
|
|
666
|
+
if (response.status === 204) {
|
|
667
|
+
commit("DELETE_ANNOTATION", annotationId);
|
|
668
|
+
commit("SET_FINISHED_REVIEW", getters.isDocumentReviewFinished());
|
|
669
|
+
resolve(true);
|
|
670
|
+
}
|
|
671
|
+
})
|
|
672
|
+
.catch((error) => {
|
|
673
|
+
reject(error.response);
|
|
674
|
+
console.log(error);
|
|
675
|
+
});
|
|
676
|
+
});
|
|
677
|
+
},
|
|
678
|
+
|
|
679
|
+
updateDocument: ({ commit, state, getters, dispatch }, updatedDocument) => {
|
|
680
|
+
return new Promise((resolve, reject) => {
|
|
681
|
+
HTTP.patch(`/documents/${state.documentId}/`, updatedDocument)
|
|
682
|
+
.then((response) => {
|
|
683
|
+
if (response.status === 200) {
|
|
684
|
+
commit("SET_SELECTED_DOCUMENT", response.data);
|
|
685
|
+
commit("SET_FINISHED_REVIEW", getters.isDocumentReviewFinished());
|
|
686
|
+
|
|
687
|
+
dispatch("pollDocumentEndpoint");
|
|
688
|
+
|
|
689
|
+
resolve(true);
|
|
690
|
+
}
|
|
691
|
+
})
|
|
692
|
+
.catch((error) => {
|
|
693
|
+
reject(error.response);
|
|
694
|
+
console.log(error);
|
|
695
|
+
});
|
|
696
|
+
});
|
|
697
|
+
},
|
|
698
|
+
|
|
699
|
+
fetchMissingAnnotations: ({ commit, state, getters }) => {
|
|
700
|
+
return HTTP.get(
|
|
701
|
+
`/missing-annotations/?document=${state.documentId}&limit=100`
|
|
702
|
+
)
|
|
703
|
+
.then((response) => {
|
|
704
|
+
commit("SET_MISSING_ANNOTATIONS", response.data.results);
|
|
705
|
+
commit("SET_FINISHED_REVIEW", getters.isDocumentReviewFinished());
|
|
706
|
+
})
|
|
707
|
+
.catch((error) => {
|
|
708
|
+
console.log(error);
|
|
709
|
+
});
|
|
710
|
+
},
|
|
711
|
+
|
|
712
|
+
addMissingAnnotations: ({ commit, dispatch }, missingAnnotations) => {
|
|
713
|
+
return new Promise((resolve, reject) => {
|
|
714
|
+
return HTTP.post(`/missing-annotations/`, missingAnnotations)
|
|
715
|
+
.then((response) => {
|
|
716
|
+
if (response.status === 201) {
|
|
717
|
+
commit("SET_REJECTED_MISSING_ANNOTATIONS", null);
|
|
718
|
+
dispatch("fetchMissingAnnotations");
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
resolve(response);
|
|
722
|
+
})
|
|
723
|
+
.catch((error) => {
|
|
724
|
+
reject(error.response);
|
|
725
|
+
console.log(error);
|
|
726
|
+
});
|
|
727
|
+
});
|
|
728
|
+
},
|
|
729
|
+
|
|
730
|
+
deleteMissingAnnotation: ({ commit, getters, dispatch }, id) => {
|
|
731
|
+
return new Promise((resolve) => {
|
|
732
|
+
return HTTP.delete(`/missing-annotations/${id}/`)
|
|
733
|
+
.then((response) => {
|
|
734
|
+
if (response.status === 204) {
|
|
735
|
+
dispatch("fetchMissingAnnotations");
|
|
736
|
+
resolve(true);
|
|
737
|
+
}
|
|
738
|
+
})
|
|
739
|
+
.catch((error) => {
|
|
740
|
+
resolve(error.response);
|
|
741
|
+
console.log(error);
|
|
742
|
+
});
|
|
743
|
+
});
|
|
744
|
+
},
|
|
745
|
+
|
|
746
|
+
updateMultipleAnnotations: ({ state, commit }, annotations) => {
|
|
747
|
+
commit("SET_NEW_ACCEPTED_ANNOTATIONS", annotations.ids);
|
|
748
|
+
|
|
749
|
+
return new Promise((resolve, reject) => {
|
|
750
|
+
return HTTP.patch(
|
|
751
|
+
`documents/${state.documentId}/update-annotations/`,
|
|
752
|
+
annotations
|
|
753
|
+
)
|
|
754
|
+
.then((response) => {
|
|
755
|
+
if (response.status === 200) {
|
|
756
|
+
response.data.map((annotation) => {
|
|
757
|
+
commit("UPDATE_ANNOTATION", annotation);
|
|
758
|
+
});
|
|
759
|
+
commit("SET_NEW_ACCEPTED_ANNOTATIONS", null);
|
|
760
|
+
resolve(true);
|
|
761
|
+
}
|
|
762
|
+
})
|
|
763
|
+
.catch((error) => {
|
|
764
|
+
console.log(error);
|
|
765
|
+
reject(error.response);
|
|
766
|
+
});
|
|
767
|
+
});
|
|
768
|
+
},
|
|
769
|
+
|
|
770
|
+
fetchDocumentStatus: ({ state, getters }) => {
|
|
771
|
+
return new Promise((resolve, reject) => {
|
|
772
|
+
return HTTP.get(
|
|
773
|
+
`documents/${state.documentId}/?fields=status_data,labeling_available`
|
|
774
|
+
)
|
|
775
|
+
.then((response) => {
|
|
776
|
+
if (getters.isDocumentReadyToBeReviewed(response.data)) {
|
|
777
|
+
// ready
|
|
778
|
+
return resolve(true);
|
|
779
|
+
} else if (getters.documentHadErrorDuringExtraction(response.data)) {
|
|
780
|
+
// error
|
|
781
|
+
return reject();
|
|
782
|
+
} else {
|
|
783
|
+
// not yet ready
|
|
784
|
+
return resolve(false);
|
|
785
|
+
}
|
|
786
|
+
})
|
|
787
|
+
.catch((error) => {
|
|
788
|
+
console.log(error);
|
|
789
|
+
});
|
|
790
|
+
});
|
|
791
|
+
},
|
|
792
|
+
|
|
793
|
+
// Get document data
|
|
794
|
+
fetchDocumentData: ({ state }) => {
|
|
795
|
+
return new Promise((resolve, reject) => {
|
|
796
|
+
HTTP.get(`documents/${state.documentId}/`)
|
|
797
|
+
.then((response) => {
|
|
798
|
+
return resolve(response.data);
|
|
799
|
+
})
|
|
800
|
+
.catch((error) => {
|
|
801
|
+
reject(error);
|
|
802
|
+
console.log(error);
|
|
803
|
+
});
|
|
804
|
+
});
|
|
805
|
+
},
|
|
806
|
+
|
|
807
|
+
// Poll Document endpoint to know if the Document is ready to be reviewed
|
|
808
|
+
// or even if there was an error during the extraction
|
|
809
|
+
pollDocumentEndpoint: ({ dispatch }) => {
|
|
810
|
+
return dispatch("fetchDocumentStatus")
|
|
811
|
+
.then((ready) => {
|
|
812
|
+
if (ready) {
|
|
813
|
+
// Stop document recalculating annotations
|
|
814
|
+
dispatch("endRecalculatingAnnotations");
|
|
815
|
+
dispatch("fetchDocument");
|
|
816
|
+
} else {
|
|
817
|
+
sleep(documentPollDuration);
|
|
818
|
+
dispatch("pollDocumentEndpoint");
|
|
819
|
+
}
|
|
820
|
+
})
|
|
821
|
+
.catch((error) => {
|
|
822
|
+
dispatch("setDocumentError", true);
|
|
823
|
+
console.log(error);
|
|
824
|
+
});
|
|
825
|
+
},
|
|
826
|
+
|
|
827
|
+
createErrorMessage: (
|
|
828
|
+
{ commit, dispatch },
|
|
829
|
+
{ error, serverErrorMessage, defaultErrorMessage }
|
|
830
|
+
) => {
|
|
831
|
+
let errorAsString;
|
|
832
|
+
|
|
833
|
+
if (error && error.status) {
|
|
834
|
+
errorAsString = error.status.toString();
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// check type of error
|
|
838
|
+
if (error.data && error.data.length > 0) {
|
|
839
|
+
dispatch("setErrorMessage", error.data[0]);
|
|
840
|
+
} else if (errorAsString.startsWith("5")) {
|
|
841
|
+
dispatch("setErrorMessage", serverErrorMessage);
|
|
842
|
+
commit("SET_SERVER_ERROR", true);
|
|
843
|
+
} else {
|
|
844
|
+
dispatch("setErrorMessage", defaultErrorMessage);
|
|
845
|
+
}
|
|
846
|
+
},
|
|
847
|
+
|
|
848
|
+
closeErrorMessage: ({ commit }) => {
|
|
849
|
+
setTimeout(() => {
|
|
850
|
+
commit("SET_ERROR_MESSAGE", null);
|
|
851
|
+
commit("SET_SHOW_ACTION_ERROR", false);
|
|
852
|
+
commit("SET_SERVER_ERROR", false);
|
|
853
|
+
}, 5000);
|
|
854
|
+
},
|
|
855
|
+
|
|
856
|
+
contactSupport: ({ rootState }, error) => {
|
|
857
|
+
let url;
|
|
858
|
+
const params = `project=${rootState.project.projectId}&email=${rootState.project.currentUser}&issue=${error}`;
|
|
859
|
+
|
|
860
|
+
if (process.env.VUE_APP_I18N_LOCALE == "de") {
|
|
861
|
+
url = "https://konfuzio.com/de/support/";
|
|
862
|
+
} else {
|
|
863
|
+
url = "https://konfuzio.com/en/support/";
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
window.open(`${url}?${params}`, "_blank");
|
|
867
|
+
},
|
|
868
|
+
};
|
|
869
|
+
|
|
870
|
+
const mutations = {
|
|
871
|
+
SET_LOADING: (state, loading) => {
|
|
872
|
+
state.loading = loading;
|
|
873
|
+
},
|
|
874
|
+
SET_DOC_ID: (state, id) => {
|
|
875
|
+
if (id !== state.documentId) {
|
|
876
|
+
state.documentId = id;
|
|
877
|
+
}
|
|
878
|
+
},
|
|
879
|
+
ADD_ANNOTATION: (state, annotation) => {
|
|
880
|
+
state.annotations.push(annotation);
|
|
881
|
+
state.annotationSets.map((annotationSet) => {
|
|
882
|
+
if (
|
|
883
|
+
annotation.annotation_set === annotationSet.id &&
|
|
884
|
+
annotation.label_set &&
|
|
885
|
+
annotationSet.label_set.id === annotation.label_set.id
|
|
886
|
+
) {
|
|
887
|
+
annotationSet.labels.map((label) => {
|
|
888
|
+
if (annotation.label && annotation.label.id === label.id) {
|
|
889
|
+
const exists = label.annotations.find(
|
|
890
|
+
(existingAnnotation) => existingAnnotation.id === annotation.id
|
|
891
|
+
);
|
|
892
|
+
if (!exists) {
|
|
893
|
+
label.annotations.push(annotation);
|
|
894
|
+
return;
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
});
|
|
898
|
+
}
|
|
899
|
+
});
|
|
900
|
+
},
|
|
901
|
+
UPDATE_ANNOTATION: (state, annotation) => {
|
|
902
|
+
const indexOfAnnotationInAnnotations = state.annotations.findIndex(
|
|
903
|
+
(existingAnnotation) => existingAnnotation.id === annotation.id
|
|
904
|
+
);
|
|
905
|
+
if (indexOfAnnotationInAnnotations > -1) {
|
|
906
|
+
state.annotations[indexOfAnnotationInAnnotations] = annotation;
|
|
907
|
+
}
|
|
908
|
+
let updatedAnnotation = false;
|
|
909
|
+
state.annotationSets.forEach((annotationSet) => {
|
|
910
|
+
if (updatedAnnotation) {
|
|
911
|
+
return;
|
|
912
|
+
}
|
|
913
|
+
annotationSet.labels.forEach((label) => {
|
|
914
|
+
const indexOfAnnotationAnnotationSets = label.annotations.findIndex(
|
|
915
|
+
(existingAnnotation) => existingAnnotation.id === annotation.id
|
|
916
|
+
);
|
|
917
|
+
if (indexOfAnnotationAnnotationSets > -1) {
|
|
918
|
+
label.annotations.splice(
|
|
919
|
+
indexOfAnnotationAnnotationSets,
|
|
920
|
+
1,
|
|
921
|
+
annotation
|
|
922
|
+
);
|
|
923
|
+
updatedAnnotation = true;
|
|
924
|
+
return;
|
|
925
|
+
}
|
|
926
|
+
});
|
|
927
|
+
});
|
|
928
|
+
},
|
|
929
|
+
DELETE_ANNOTATION: (state, annotationId) => {
|
|
930
|
+
const indexOfAnnotationToDelete = state.annotations.findIndex(
|
|
931
|
+
(existingAnnotation) => existingAnnotation.id === annotationId
|
|
932
|
+
);
|
|
933
|
+
if (indexOfAnnotationToDelete > -1) {
|
|
934
|
+
state.annotations.splice(indexOfAnnotationToDelete, 1);
|
|
935
|
+
}
|
|
936
|
+
let deleted = false;
|
|
937
|
+
state.annotationSets.forEach((annotationSet) => {
|
|
938
|
+
if (deleted) {
|
|
939
|
+
return;
|
|
940
|
+
}
|
|
941
|
+
annotationSet.labels.forEach((label) => {
|
|
942
|
+
const indexOfAnnotationInLabelToDelete = label.annotations.findIndex(
|
|
943
|
+
(existingAnnotation) => existingAnnotation.id === annotationId
|
|
944
|
+
);
|
|
945
|
+
if (indexOfAnnotationInLabelToDelete > -1) {
|
|
946
|
+
label.annotations.splice(indexOfAnnotationInLabelToDelete, 1);
|
|
947
|
+
deleted = true;
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
950
|
+
});
|
|
951
|
+
});
|
|
952
|
+
},
|
|
953
|
+
SET_ANNOTATIONS: (state, annotations) => {
|
|
954
|
+
state.annotations = annotations;
|
|
955
|
+
},
|
|
956
|
+
SET_ANNOTATION_SETS: (state, annotationSets) => {
|
|
957
|
+
state.annotationSets = annotationSets;
|
|
958
|
+
},
|
|
959
|
+
SET_LABELS: (state, labels) => {
|
|
960
|
+
state.labels = labels;
|
|
961
|
+
},
|
|
962
|
+
SET_ANNOTATION_SELECTED: (state, annotation) => {
|
|
963
|
+
state.sidebarAnnotationSelected = annotation;
|
|
964
|
+
},
|
|
965
|
+
SET_EDIT_ANNOTATION: (state, editAnnotation) => {
|
|
966
|
+
state.editAnnotation = editAnnotation;
|
|
967
|
+
},
|
|
968
|
+
SET_FINISHED_REVIEW: (state, finishedReview) => {
|
|
969
|
+
state.finishedReview = finishedReview;
|
|
970
|
+
},
|
|
971
|
+
RESET_EDIT_ANNOTATION: (state) => {
|
|
972
|
+
state.editAnnotation = null;
|
|
973
|
+
},
|
|
974
|
+
ADD_PAGE: (state, page) => {
|
|
975
|
+
// if we already have the page in the state, update it in
|
|
976
|
+
// the pages array instead of creating a new one
|
|
977
|
+
const existingPageIndex = state.pages.findIndex(
|
|
978
|
+
(p) => p.number === page.number
|
|
979
|
+
);
|
|
980
|
+
if (existingPageIndex === -1) {
|
|
981
|
+
state.pages.push(page);
|
|
982
|
+
} else {
|
|
983
|
+
state.pages[existingPageIndex] = page;
|
|
984
|
+
}
|
|
985
|
+
},
|
|
986
|
+
SET_PAGES: (state, pages) => {
|
|
987
|
+
state.pages = pages;
|
|
988
|
+
},
|
|
989
|
+
SET_DOCUMENT_ANNOTATION_SELECTED: (state, documentAnnotationSelected) => {
|
|
990
|
+
state.documentAnnotationSelected = documentAnnotationSelected;
|
|
991
|
+
},
|
|
992
|
+
SET_DOCUMENT_ANNOTATION_SCROLL: (state, scrollTo) => {
|
|
993
|
+
if (state.documentAnnotationSelected) {
|
|
994
|
+
state.documentAnnotationSelected.scrollTo = scrollTo;
|
|
995
|
+
}
|
|
996
|
+
},
|
|
997
|
+
SET_SELECTED_DOCUMENT: (state, document) => {
|
|
998
|
+
if (document.is_reviewed === true) {
|
|
999
|
+
state.publicView = true;
|
|
1000
|
+
}
|
|
1001
|
+
state.selectedDocument = document;
|
|
1002
|
+
|
|
1003
|
+
// this is to handle cache when a document is edited or changed
|
|
1004
|
+
state.selectedDocument.downloaded_at = Date.now();
|
|
1005
|
+
},
|
|
1006
|
+
SET_RECALCULATING_ANNOTATIONS: (state, recalculatingAnnotations) => {
|
|
1007
|
+
state.recalculatingAnnotations = recalculatingAnnotations;
|
|
1008
|
+
},
|
|
1009
|
+
SET_MISSING_ANNOTATIONS: (state, missingAnnotations) => {
|
|
1010
|
+
state.missingAnnotations = missingAnnotations;
|
|
1011
|
+
},
|
|
1012
|
+
|
|
1013
|
+
SET_SHOW_ACTION_ERROR: (state, value) => {
|
|
1014
|
+
state.showActionError = value;
|
|
1015
|
+
},
|
|
1016
|
+
SET_ERROR_MESSAGE: (state, message) => {
|
|
1017
|
+
state.errorMessage = message;
|
|
1018
|
+
},
|
|
1019
|
+
SET_DOCUMENT_ERROR: (state, value) => {
|
|
1020
|
+
state.showDocumentError = value;
|
|
1021
|
+
},
|
|
1022
|
+
SET_REJECTED_MISSING_ANNOTATIONS: (state, annotations) => {
|
|
1023
|
+
state.rejectedMissingAnnotations = annotations;
|
|
1024
|
+
},
|
|
1025
|
+
SET_ERROR_MESSAGE_WIDTH: (state, width) => {
|
|
1026
|
+
state.errorMessageWidth = width;
|
|
1027
|
+
},
|
|
1028
|
+
SET_PUBLIC_VIEW: (state, value) => {
|
|
1029
|
+
state.publicView = value;
|
|
1030
|
+
},
|
|
1031
|
+
SET_DOCUMENT_IS_READY: (state, value) => {
|
|
1032
|
+
state.documentIsReady = value;
|
|
1033
|
+
},
|
|
1034
|
+
SET_DOCUMENT_HAS_ERROR: (state, value) => {
|
|
1035
|
+
state.documentHasError = value;
|
|
1036
|
+
},
|
|
1037
|
+
SET_HOVERED_ANNOTATION_SET: (state, hoveredAnnotationSet) => {
|
|
1038
|
+
state.hoveredAnnotationSet = hoveredAnnotationSet;
|
|
1039
|
+
},
|
|
1040
|
+
SET_NEW_ACCEPTED_ANNOTATIONS: (state, annotations) => {
|
|
1041
|
+
state.newAcceptedAnnotations = annotations;
|
|
1042
|
+
},
|
|
1043
|
+
SET_SELECTED_ENTITIES: (state, entities) => {
|
|
1044
|
+
state.selectedEntities = entities;
|
|
1045
|
+
},
|
|
1046
|
+
SET_SERVER_ERROR: (state, value) => {
|
|
1047
|
+
state.serverError = value;
|
|
1048
|
+
},
|
|
1049
|
+
};
|
|
1050
|
+
|
|
1051
|
+
export default {
|
|
1052
|
+
namespaced: true,
|
|
1053
|
+
state,
|
|
1054
|
+
getters,
|
|
1055
|
+
actions,
|
|
1056
|
+
mutations,
|
|
1057
|
+
};
|