@konfuzio/document-validation-ui 0.1.19-dev.2 → 0.1.19
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 +10 -10
- package/.prettierrc.json +1 -1
- package/LICENSE +21 -21
- package/README.md +24 -24
- package/cypress.config.js +13 -13
- package/dist/js/app.js +1 -1
- package/dist/js/app.js.map +1 -1
- package/dist/js/chunk-vendors.js +1 -1
- package/dist/js/chunk-vendors.js.map +1 -1
- package/jest.config.js +4 -4
- package/package.json +66 -66
- package/src/api.js +82 -82
- package/src/assets/images/AcceptedCheckMark.vue +8 -8
- package/src/assets/images/AcceptedUser.vue +8 -8
- package/src/assets/images/ActionIcon.vue +60 -60
- package/src/assets/images/ArrowDownKey.vue +11 -11
- package/src/assets/images/ArrowUpKey.vue +11 -11
- package/src/assets/images/CategoryIconImg.vue +13 -13
- package/src/assets/images/CheckMark.vue +8 -8
- package/src/assets/images/DraggableIcon.vue +14 -14
- package/src/assets/images/EditDocIcon.vue +12 -12
- package/src/assets/images/EmptyStateImg.vue +129 -129
- package/src/assets/images/ErrorIcon.vue +28 -28
- package/src/assets/images/EyeIcon.vue +11 -11
- package/src/assets/images/FileNameNotSavedImage.vue +26 -26
- package/src/assets/images/FileNameSavedImage.vue +14 -14
- package/src/assets/images/FitZoomIcon.vue +16 -16
- package/src/assets/images/GridIcon.vue +16 -16
- package/src/assets/images/KeyboardIcon.vue +16 -16
- package/src/assets/images/MagicWandIcon.vue +16 -16
- package/src/assets/images/MinusIcon.vue +13 -13
- package/src/assets/images/NotFoundIcon.vue +16 -16
- package/src/assets/images/NotOptimizedIllustration.vue +651 -651
- package/src/assets/images/PlusIcon.vue +13 -13
- package/src/assets/images/QuestionMark.vue +12 -12
- package/src/assets/images/ServerImage.vue +73 -73
- package/src/assets/images/SettingsIcon.vue +14 -14
- package/src/assets/images/SplitLines.vue +18 -18
- package/src/assets/images/SplitZigZag.vue +49 -49
- package/src/assets/images/StarIcon.vue +16 -16
- package/src/assets/images/StatusImg.vue +14 -14
- package/src/assets/images/TranslateArrows.vue +33 -33
- package/src/assets/scss/ann_set_table_options.scss +26 -26
- package/src/assets/scss/annotation_details.scss +141 -141
- package/src/assets/scss/choose_label_set_modal.scss +65 -65
- package/src/assets/scss/document_action_bar.scss +37 -37
- package/src/assets/scss/document_annotations.scss +558 -558
- package/src/assets/scss/document_category.scss +85 -85
- package/src/assets/scss/document_dashboard.scss +52 -52
- package/src/assets/scss/document_edit.scss +410 -410
- package/src/assets/scss/document_error.scss +81 -81
- package/src/assets/scss/document_name.scss +60 -60
- package/src/assets/scss/document_page.scss +12 -12
- package/src/assets/scss/document_thumbnails.scss +41 -41
- package/src/assets/scss/document_toolbar.scss +111 -111
- package/src/assets/scss/document_top_bar.scss +171 -171
- package/src/assets/scss/document_viewport_modal.scss +25 -25
- package/src/assets/scss/documents_list.scss +141 -141
- package/src/assets/scss/edit_page_thumbnail.scss +53 -53
- package/src/assets/scss/empty_state.scss +34 -34
- package/src/assets/scss/extracting_data.scss +35 -35
- package/src/assets/scss/imports.scss +1 -1
- package/src/assets/scss/multi_ann_table_overlay.scss +38 -38
- package/src/assets/scss/multi_ann_table_popup.scss +12 -12
- package/src/assets/scss/new_annotation.scss +102 -102
- package/src/assets/scss/scrolling_document.scss +19 -19
- package/src/assets/scss/theme.scss +801 -801
- package/src/assets/scss/variables.scss +66 -66
- package/src/components/App.cy.js +7 -7
- package/src/components/App.vue +187 -187
- package/src/components/DocumentAnnotations/AnnotationActionButtons.vue +152 -152
- package/src/components/DocumentAnnotations/AnnotationContent.vue +210 -210
- package/src/components/DocumentAnnotations/AnnotationDetails.vue +251 -251
- package/src/components/DocumentAnnotations/AnnotationRow.vue +752 -752
- package/src/components/DocumentAnnotations/AnnotationSetActionButtons.vue +89 -89
- package/src/components/DocumentAnnotations/ChooseLabelSetModal.vue +186 -186
- package/src/components/DocumentAnnotations/DocumentAnnotations.cy.js +441 -441
- package/src/components/DocumentAnnotations/DocumentAnnotations.vue +534 -534
- package/src/components/DocumentAnnotations/DocumentLabel.vue +189 -189
- package/src/components/DocumentAnnotations/EmptyAnnotation.vue +193 -193
- package/src/components/DocumentAnnotations/EmptyState.vue +21 -21
- package/src/components/DocumentAnnotations/ExtractingData.vue +41 -41
- package/src/components/DocumentAnnotations/LoadingAnnotations.vue +43 -43
- package/src/components/DocumentAnnotations/LoadingLabels.vue +43 -43
- package/src/components/DocumentAnnotations/MultiAnnotationTableOverlay.vue +338 -338
- package/src/components/DocumentAnnotations/index.js +8 -8
- package/src/components/DocumentCategory.vue +281 -281
- package/src/components/DocumentDashboard.vue +170 -170
- package/src/components/DocumentEdit/DocumentEdit.cy.js +541 -541
- package/src/components/DocumentEdit/DocumentEdit.vue +503 -503
- package/src/components/DocumentEdit/EditConfirmationModal.vue +55 -55
- package/src/components/DocumentEdit/EditPageThumbnail.vue +114 -114
- package/src/components/DocumentEdit/EditPages.vue +161 -161
- package/src/components/DocumentEdit/EditSidebar.vue +154 -154
- package/src/components/DocumentEdit/RenameAndCategorize.vue +184 -184
- package/src/components/DocumentEdit/SidebarButtons.vue +53 -53
- package/src/components/DocumentEdit/SplitInfoBar.vue +21 -21
- package/src/components/DocumentEdit/index.js +4 -4
- package/src/components/DocumentModals/DocumentErrorModal.vue +58 -58
- package/src/components/DocumentModals/NotOptimizedViewportModal.vue +51 -51
- package/src/components/DocumentPage/ActionBar.vue +48 -48
- package/src/components/DocumentPage/AnnSetTableOptions.vue +111 -111
- package/src/components/DocumentPage/BoxSelection.vue +152 -152
- package/src/components/DocumentPage/DocumentPage.cy.js +92 -92
- package/src/components/DocumentPage/DocumentPage.vue +568 -568
- package/src/components/DocumentPage/DocumentToolbar.cy.js +215 -215
- package/src/components/DocumentPage/DocumentToolbar.vue +228 -228
- package/src/components/DocumentPage/DummyPage.vue +55 -55
- package/src/components/DocumentPage/MultiAnnSelection.vue +371 -371
- package/src/components/DocumentPage/NewAnnotation.vue +308 -308
- package/src/components/DocumentPage/ScrollingDocument.vue +149 -149
- package/src/components/DocumentPage/ScrollingPage.vue +179 -179
- package/src/components/DocumentPage/index.js +5 -5
- package/src/components/DocumentThumbnails/DocumentThumbnails.cy.js +67 -67
- package/src/components/DocumentThumbnails/DocumentThumbnails.vue +132 -132
- package/src/components/DocumentThumbnails/LoadingThumbnail.vue +25 -25
- package/src/components/DocumentThumbnails/index.js +1 -1
- package/src/components/DocumentTopBar/DocumentName.vue +236 -236
- package/src/components/DocumentTopBar/DocumentTopBar.cy.js +222 -222
- package/src/components/DocumentTopBar/DocumentTopBar.vue +202 -202
- package/src/components/DocumentTopBar/DocumentTopBarButtons.vue +183 -183
- package/src/components/DocumentTopBar/KeyboardActionsDescription.vue +74 -74
- package/src/components/DocumentTopBar/index.js +3 -3
- package/src/components/DocumentsList/DocumentsList.vue +121 -121
- package/src/components/DocumentsList/index.js +1 -1
- package/src/components/ErrorMessage.vue +40 -40
- package/src/components/index.js +1 -1
- package/src/constants.js +5 -5
- package/src/directives/scroll.js +28 -28
- package/src/i18n.js +22 -22
- package/src/icons.js +45 -45
- package/src/locales/de.json +148 -148
- package/src/locales/en.json +148 -148
- package/src/main.js +26 -26
- package/src/store/category.js +191 -191
- package/src/store/display.js +311 -311
- package/src/store/document.js +1438 -1438
- package/src/store/edit.js +316 -316
- package/src/store/index.js +21 -21
- package/src/store/project.js +143 -143
- package/src/store/selection.js +210 -210
- package/src/utils/utils.js +54 -54
- package/vue.config.js +25 -25
package/src/store/document.js
CHANGED
|
@@ -1,1438 +1,1438 @@
|
|
|
1
|
-
import myImports from "../api";
|
|
2
|
-
import { MULTI_ANN_TABLE_FEATURE } from "../constants";
|
|
3
|
-
import {
|
|
4
|
-
sleep,
|
|
5
|
-
getURLQueryParam,
|
|
6
|
-
navigateToNewDocumentURL,
|
|
7
|
-
getURLPath,
|
|
8
|
-
} from "../utils/utils";
|
|
9
|
-
|
|
10
|
-
const HTTP = myImports.HTTP;
|
|
11
|
-
const documentPollDuration = 1000;
|
|
12
|
-
export const table_reference_api = "api.v3.dvui.table";
|
|
13
|
-
|
|
14
|
-
const state = {
|
|
15
|
-
loading: true,
|
|
16
|
-
pages: [],
|
|
17
|
-
annotationSets: null,
|
|
18
|
-
annotations: null,
|
|
19
|
-
labels: [],
|
|
20
|
-
documentId: process.env.VUE_APP_DOCUMENT_ID,
|
|
21
|
-
sidebarAnnotationSelected: null,
|
|
22
|
-
documentAnnotationSelected: null,
|
|
23
|
-
selectedDocument: null,
|
|
24
|
-
recalculatingAnnotations: false,
|
|
25
|
-
editAnnotation: null,
|
|
26
|
-
missingAnnotations: [],
|
|
27
|
-
publicView: true,
|
|
28
|
-
showActionError: false,
|
|
29
|
-
errorMessage: null,
|
|
30
|
-
showDocumentError: false,
|
|
31
|
-
annotationsMarkedAsMissing: null,
|
|
32
|
-
errorMessageWidth: null,
|
|
33
|
-
hoveredAnnotationSet: null,
|
|
34
|
-
newAcceptedAnnotations: null,
|
|
35
|
-
serverError: false,
|
|
36
|
-
splittingSuggestions: null,
|
|
37
|
-
enableGroupingFeature: true,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const getters = {
|
|
41
|
-
/**
|
|
42
|
-
* Get entities inside a box
|
|
43
|
-
*/
|
|
44
|
-
entitiesOnSelection: (state) => (box, page) => {
|
|
45
|
-
return page.entities.filter(
|
|
46
|
-
(entity) =>
|
|
47
|
-
box.x0 <= entity.x0 &&
|
|
48
|
-
box.x1 >= entity.x1 &&
|
|
49
|
-
box.y0 <= entity.y0 &&
|
|
50
|
-
box.y1 >= entity.y1
|
|
51
|
-
);
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Number of pages. If the pages array doesn't exist yet, return 0.
|
|
56
|
-
*/
|
|
57
|
-
pageCount: (state) => {
|
|
58
|
-
if (state.selectedDocument.pages) {
|
|
59
|
-
return state.selectedDocument.pages.length;
|
|
60
|
-
}
|
|
61
|
-
return 0;
|
|
62
|
-
},
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Returns the current page
|
|
66
|
-
*/
|
|
67
|
-
pageSelected: (state, _, rootState) => {
|
|
68
|
-
if (state.pages) {
|
|
69
|
-
return state.pages[rootState.display.currentPage - 1];
|
|
70
|
-
}
|
|
71
|
-
return null;
|
|
72
|
-
},
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Returns a page in the given index
|
|
76
|
-
*/
|
|
77
|
-
pageAtIndex: (state) => (index) => {
|
|
78
|
-
if (state.selectedDocument && state.selectedDocument.pages) {
|
|
79
|
-
return state.selectedDocument.pages[index];
|
|
80
|
-
}
|
|
81
|
-
return null;
|
|
82
|
-
},
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Checks if is to scroll to an annotation in the document
|
|
86
|
-
*/
|
|
87
|
-
scrollDocumentToAnnotation: (state) => {
|
|
88
|
-
return (
|
|
89
|
-
state.documentAnnotationSelected &&
|
|
90
|
-
state.documentAnnotationSelected.scrollTo
|
|
91
|
-
);
|
|
92
|
-
},
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Checks if the document is categorized and ready to start the review
|
|
96
|
-
*/
|
|
97
|
-
categorizationIsConfirmed: (state) => {
|
|
98
|
-
if (state.selectedDocument) {
|
|
99
|
-
if (
|
|
100
|
-
state.selectedDocument.category_is_revised ||
|
|
101
|
-
state.selectedDocument.is_reviewed
|
|
102
|
-
) {
|
|
103
|
-
return true;
|
|
104
|
-
} else if (!state.selectedDocument.category) {
|
|
105
|
-
return false;
|
|
106
|
-
} else {
|
|
107
|
-
// check if there's any annotation already approved
|
|
108
|
-
const found = state.annotations.find((annotation) => {
|
|
109
|
-
return annotation.revised;
|
|
110
|
-
});
|
|
111
|
-
return found != undefined;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
return false;
|
|
115
|
-
},
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Gets labels for an annotation creation from a label/annotation set
|
|
119
|
-
*/
|
|
120
|
-
labelsFilteredForAnnotationCreation: (_, getters) => (set) => {
|
|
121
|
-
let availableLabels = [];
|
|
122
|
-
if (set.id && set.labels) {
|
|
123
|
-
// check if label can be multiple, if there's already an annotation created & if it's a negative annotation
|
|
124
|
-
set.labels.map((label) => {
|
|
125
|
-
// check if we already added the same label to the array
|
|
126
|
-
const found = availableLabels.find((l) => l.id === label.id);
|
|
127
|
-
|
|
128
|
-
if (found) return;
|
|
129
|
-
|
|
130
|
-
if (label.annotations.length === 0) {
|
|
131
|
-
availableLabels.push(label);
|
|
132
|
-
} else {
|
|
133
|
-
if (label.has_multiple_top_candidates) {
|
|
134
|
-
availableLabels.push(label);
|
|
135
|
-
} else {
|
|
136
|
-
// if the label has negative annotations, we show the label
|
|
137
|
-
label.annotations.map((annotation) => {
|
|
138
|
-
if (getters.isNegative(annotation)) {
|
|
139
|
-
availableLabels.push(label);
|
|
140
|
-
}
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
} else if (set.labels) {
|
|
146
|
-
// if not existing ann set, then return all labels
|
|
147
|
-
availableLabels = set.labels;
|
|
148
|
-
}
|
|
149
|
-
return availableLabels;
|
|
150
|
-
},
|
|
151
|
-
|
|
152
|
-
/* Checks if annotation is in deleted state */
|
|
153
|
-
isAnnotationDeleted: (state) => (annotation) => {
|
|
154
|
-
if (annotation) {
|
|
155
|
-
return annotation.revised && !annotation.is_correct;
|
|
156
|
-
}
|
|
157
|
-
return false;
|
|
158
|
-
},
|
|
159
|
-
|
|
160
|
-
/* Checks if the label has annotations to show */
|
|
161
|
-
labelHasAnnotations: (_, getters) => (label) => {
|
|
162
|
-
const annotations = label.annotations.filter((annotation) => {
|
|
163
|
-
return !getters.isAnnotationDeleted(annotation);
|
|
164
|
-
});
|
|
165
|
-
return annotations.length > 0;
|
|
166
|
-
},
|
|
167
|
-
|
|
168
|
-
/* Checks if the document has an annotation set */
|
|
169
|
-
annotationSetExists: (state) => (annotationSetId) => {
|
|
170
|
-
return state.annotationSets.find((annSet) => annSet.id === annotationSetId);
|
|
171
|
-
},
|
|
172
|
-
|
|
173
|
-
/* Get annotation sets created in table */
|
|
174
|
-
annotationSetsInTable: (state) => () => {
|
|
175
|
-
const annotationSetsList = {};
|
|
176
|
-
if (MULTI_ANN_TABLE_FEATURE) {
|
|
177
|
-
state.annotationSets.forEach((annotationSet) => {
|
|
178
|
-
let addAnnotationSet = false;
|
|
179
|
-
if (annotationSet.labels) {
|
|
180
|
-
annotationSet.labels.forEach((label) => {
|
|
181
|
-
if (
|
|
182
|
-
label.annotations &&
|
|
183
|
-
label.annotations.find(
|
|
184
|
-
(annotation) =>
|
|
185
|
-
annotation.origin && annotation.origin === table_reference_api
|
|
186
|
-
)
|
|
187
|
-
) {
|
|
188
|
-
addAnnotationSet = true;
|
|
189
|
-
return;
|
|
190
|
-
}
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
if (addAnnotationSet) {
|
|
194
|
-
// group by label set
|
|
195
|
-
if (annotationSetsList[`${annotationSet.label_set.id}`]) {
|
|
196
|
-
annotationSetsList[`${annotationSet.label_set.id}`].push(
|
|
197
|
-
annotationSet
|
|
198
|
-
);
|
|
199
|
-
} else {
|
|
200
|
-
annotationSetsList[`${annotationSet.label_set.id}`] = [
|
|
201
|
-
annotationSet,
|
|
202
|
-
];
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
return annotationSetsList;
|
|
208
|
-
},
|
|
209
|
-
|
|
210
|
-
/* Get annotation sets without tables */
|
|
211
|
-
annotationSetsToShowInList: (state) => () => {
|
|
212
|
-
const annotationSetsList = [];
|
|
213
|
-
state.annotationSets.forEach((annotationSet) => {
|
|
214
|
-
let addAnnotationSet = true;
|
|
215
|
-
if (annotationSet.labels) {
|
|
216
|
-
annotationSet.labels.forEach((label) => {
|
|
217
|
-
if (
|
|
218
|
-
MULTI_ANN_TABLE_FEATURE &&
|
|
219
|
-
label.annotations &&
|
|
220
|
-
label.annotations.find(
|
|
221
|
-
(annotation) =>
|
|
222
|
-
annotation.origin && annotation.origin === table_reference_api
|
|
223
|
-
)
|
|
224
|
-
) {
|
|
225
|
-
addAnnotationSet = false;
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
if (addAnnotationSet) {
|
|
231
|
-
annotationSetsList.push(annotationSet);
|
|
232
|
-
}
|
|
233
|
-
});
|
|
234
|
-
return annotationSetsList;
|
|
235
|
-
},
|
|
236
|
-
|
|
237
|
-
/* Get annotations inside a list of annotation sets */
|
|
238
|
-
annotationsInAnnotationsSets: (state) => (annotationsSets) => {
|
|
239
|
-
const annotations = [];
|
|
240
|
-
annotationsSets.forEach((annotationSet) => {
|
|
241
|
-
annotationSet.labels.forEach((label) => {
|
|
242
|
-
label.annotations.forEach((annotation) => {
|
|
243
|
-
annotations.push(annotation);
|
|
244
|
-
});
|
|
245
|
-
});
|
|
246
|
-
});
|
|
247
|
-
return annotations;
|
|
248
|
-
},
|
|
249
|
-
|
|
250
|
-
/* Process annotations and extract labels and sets */
|
|
251
|
-
processAnnotationSets: (state, getters) => (annotationSets) => {
|
|
252
|
-
// group annotations for sidebar
|
|
253
|
-
const annotations = [];
|
|
254
|
-
const labels = [];
|
|
255
|
-
const processedAnnotationSets = annotationSets.map((annotationSet) => {
|
|
256
|
-
const annotationSetLabels = annotationSet.labels.map((label) => {
|
|
257
|
-
// add annotations to the document array
|
|
258
|
-
annotations.push(...label.annotations);
|
|
259
|
-
labels.push(label);
|
|
260
|
-
// add labels to the labels array
|
|
261
|
-
return label;
|
|
262
|
-
});
|
|
263
|
-
annotationSet.labels = annotationSetLabels;
|
|
264
|
-
return annotationSet;
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
return {
|
|
268
|
-
annotationSets: processedAnnotationSets,
|
|
269
|
-
labels,
|
|
270
|
-
annotations,
|
|
271
|
-
};
|
|
272
|
-
},
|
|
273
|
-
|
|
274
|
-
/* Checks if there are annotations correct in the document */
|
|
275
|
-
documentHasCorrectAnnotations: (state) => {
|
|
276
|
-
if (
|
|
277
|
-
!state.annotations ||
|
|
278
|
-
(state.annotations &&
|
|
279
|
-
state.annotations.filter((ann) => ann.is_correct).length > 0)
|
|
280
|
-
) {
|
|
281
|
-
return true;
|
|
282
|
-
}
|
|
283
|
-
return false;
|
|
284
|
-
},
|
|
285
|
-
|
|
286
|
-
/* Returns the number of accepted annotations in a label */
|
|
287
|
-
numberOfAcceptedAnnotationsInLabel: (_) => (label) => {
|
|
288
|
-
const annotations = label.annotations.filter((annotation) => {
|
|
289
|
-
return annotation.revised && annotation.is_correct;
|
|
290
|
-
});
|
|
291
|
-
return annotations.length;
|
|
292
|
-
},
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* Checks if theres a group of annotation sets and add an index number to them
|
|
296
|
-
*/
|
|
297
|
-
numberOfAnnotationSetGroup: (state) => (annotationSet) => {
|
|
298
|
-
let found = false;
|
|
299
|
-
let value = 0;
|
|
300
|
-
let index = 0;
|
|
301
|
-
if (state.annotationSets) {
|
|
302
|
-
state.annotationSets.map((annotationSetTemp) => {
|
|
303
|
-
if (
|
|
304
|
-
annotationSetTemp.id !== annotationSet.id &&
|
|
305
|
-
annotationSetTemp.label_set.id === annotationSet.label_set.id &&
|
|
306
|
-
annotationSetTemp.label_set.name === annotationSet.label_set.name
|
|
307
|
-
) {
|
|
308
|
-
found = true;
|
|
309
|
-
index++;
|
|
310
|
-
} else if (
|
|
311
|
-
annotationSetTemp.label_set.id === annotationSet.label_set.id
|
|
312
|
-
) {
|
|
313
|
-
value = index;
|
|
314
|
-
}
|
|
315
|
-
});
|
|
316
|
-
return found ? `${value + 1}` : "";
|
|
317
|
-
}
|
|
318
|
-
return "";
|
|
319
|
-
},
|
|
320
|
-
|
|
321
|
-
/**
|
|
322
|
-
* Get label with annotations filtered if the label supports multiple or not
|
|
323
|
-
*/
|
|
324
|
-
annotationsInLabelFiltered: (state) => (label) => {
|
|
325
|
-
let labelToReturn;
|
|
326
|
-
if (
|
|
327
|
-
label.has_multiple_top_candidates === false &&
|
|
328
|
-
label.annotations &&
|
|
329
|
-
label.annotations.length > 1
|
|
330
|
-
) {
|
|
331
|
-
let highestConfidenceAnnotation = label.annotations[0];
|
|
332
|
-
for (let i = 1; i < label.annotations.length; i++) {
|
|
333
|
-
// check which one has more confidence or if it's the same, then check if one is revised or not
|
|
334
|
-
if (
|
|
335
|
-
highestConfidenceAnnotation.confidence <
|
|
336
|
-
label.annotations[i].confidence ||
|
|
337
|
-
(highestConfidenceAnnotation.confidence ===
|
|
338
|
-
label.annotations[i].confidence &&
|
|
339
|
-
label.annotations[i].revised)
|
|
340
|
-
) {
|
|
341
|
-
highestConfidenceAnnotation = label.annotations[i];
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
labelToReturn = {
|
|
345
|
-
...label,
|
|
346
|
-
annotations: [highestConfidenceAnnotation],
|
|
347
|
-
};
|
|
348
|
-
} else {
|
|
349
|
-
labelToReturn = {
|
|
350
|
-
...label,
|
|
351
|
-
};
|
|
352
|
-
}
|
|
353
|
-
return labelToReturn;
|
|
354
|
-
},
|
|
355
|
-
|
|
356
|
-
/**
|
|
357
|
-
* Checks if annotation is being edited
|
|
358
|
-
*/
|
|
359
|
-
isAnnotationInEditMode:
|
|
360
|
-
(state) =>
|
|
361
|
-
(annotationId, index = null) => {
|
|
362
|
-
if (state.editAnnotation && annotationId) {
|
|
363
|
-
if (index != null) {
|
|
364
|
-
return (
|
|
365
|
-
state.editAnnotation.id === annotationId &&
|
|
366
|
-
state.editAnnotation.index === index
|
|
367
|
-
);
|
|
368
|
-
}
|
|
369
|
-
return state.editAnnotation.id === annotationId;
|
|
370
|
-
}
|
|
371
|
-
},
|
|
372
|
-
|
|
373
|
-
/**
|
|
374
|
-
* Get number of empty labels per annotation set
|
|
375
|
-
*/
|
|
376
|
-
emptyLabels: (state, getters) => (annotationSet) => {
|
|
377
|
-
const pendingEmpty = [];
|
|
378
|
-
|
|
379
|
-
annotationSet.labels.map((label) => {
|
|
380
|
-
const foundMissing = state.missingAnnotations.find(
|
|
381
|
-
(l) =>
|
|
382
|
-
l.label === label.id &&
|
|
383
|
-
annotationSet.id === l.annotation_set &&
|
|
384
|
-
annotationSet.label_set.id === l.label_set
|
|
385
|
-
);
|
|
386
|
-
|
|
387
|
-
const foundNegative = label.annotations.find((annotation) =>
|
|
388
|
-
getters.isNegative(annotation)
|
|
389
|
-
);
|
|
390
|
-
|
|
391
|
-
if (!foundMissing && (label.annotations.length === 0 || foundNegative)) {
|
|
392
|
-
pendingEmpty.push(label);
|
|
393
|
-
}
|
|
394
|
-
});
|
|
395
|
-
|
|
396
|
-
return pendingEmpty;
|
|
397
|
-
},
|
|
398
|
-
|
|
399
|
-
annotationIsNotFound: (state) => (annotationSet, label) => {
|
|
400
|
-
// Check if the combined label and label set have been marked as missing
|
|
401
|
-
// or if the document is in public mode
|
|
402
|
-
if (state.missingAnnotations.length === 0) {
|
|
403
|
-
return false;
|
|
404
|
-
} else {
|
|
405
|
-
const found = state.missingAnnotations.filter(
|
|
406
|
-
(el) =>
|
|
407
|
-
el.label === label.id &&
|
|
408
|
-
el.annotation_set === annotationSet.id &&
|
|
409
|
-
el.label_set === annotationSet.label_set.id
|
|
410
|
-
);
|
|
411
|
-
return found.length !== 0;
|
|
412
|
-
}
|
|
413
|
-
},
|
|
414
|
-
|
|
415
|
-
// Check if document is ready to be finished
|
|
416
|
-
isDocumentReadyToFinishReview: (state) => {
|
|
417
|
-
// check if all annotations are correct
|
|
418
|
-
let notCorrect;
|
|
419
|
-
|
|
420
|
-
const emptyAnnotations = [];
|
|
421
|
-
|
|
422
|
-
if (state.labels.length === 0) return false;
|
|
423
|
-
|
|
424
|
-
if (state.annotationSets && state.annotationSets.length > 0) {
|
|
425
|
-
state.annotationSets.forEach((annSet) => {
|
|
426
|
-
annSet.labels.map((label) => {
|
|
427
|
-
// return only labels with empty annotations
|
|
428
|
-
if (label.annotations.length === 0) {
|
|
429
|
-
emptyAnnotations.push({
|
|
430
|
-
label: label.id,
|
|
431
|
-
label_set: annSet.label_set.id,
|
|
432
|
-
});
|
|
433
|
-
}
|
|
434
|
-
});
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
|
|
438
|
-
if (state.annotations) {
|
|
439
|
-
notCorrect = state.annotations.filter((a) => !a.is_correct);
|
|
440
|
-
|
|
441
|
-
if (notCorrect) {
|
|
442
|
-
notCorrect.map((annotation) => {
|
|
443
|
-
emptyAnnotations.push(annotation);
|
|
444
|
-
});
|
|
445
|
-
}
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// if all annotations are correct
|
|
449
|
-
// and if there are no empty annotations or
|
|
450
|
-
// all empty annotations or negative annotations were marked as missing,
|
|
451
|
-
// we can finish the review
|
|
452
|
-
if (
|
|
453
|
-
!emptyAnnotations ||
|
|
454
|
-
!state.missingAnnotations ||
|
|
455
|
-
state.missingAnnotations.length === emptyAnnotations.length
|
|
456
|
-
) {
|
|
457
|
-
return true;
|
|
458
|
-
}
|
|
459
|
-
return false;
|
|
460
|
-
},
|
|
461
|
-
|
|
462
|
-
isDocumentReviewed: (state) => {
|
|
463
|
-
return state.selectedDocument.is_reviewed;
|
|
464
|
-
},
|
|
465
|
-
|
|
466
|
-
/**
|
|
467
|
-
* Get number of annotations pending review per annotation set
|
|
468
|
-
*/
|
|
469
|
-
notCorrectAnnotations: () => (annotationSet) => {
|
|
470
|
-
const labels = annotationSet.labels.filter(
|
|
471
|
-
(label) => label.annotations.length > 0
|
|
472
|
-
);
|
|
473
|
-
|
|
474
|
-
const annotationsWithPendingReview = [];
|
|
475
|
-
|
|
476
|
-
labels.map((label) => {
|
|
477
|
-
const foundPendingAnnotations = label.annotations.filter(
|
|
478
|
-
(ann) => !ann.is_correct && !ann.revised
|
|
479
|
-
);
|
|
480
|
-
|
|
481
|
-
if (foundPendingAnnotations && foundPendingAnnotations.length > 0) {
|
|
482
|
-
foundPendingAnnotations.map((annotation) => {
|
|
483
|
-
annotationsWithPendingReview.push(annotation);
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// Check if we have grouped annotations by same label
|
|
488
|
-
if (state.enableGroupingFeature && label.annotations.length < 2) {
|
|
489
|
-
return annotationsWithPendingReview.length - label.annotations.length;
|
|
490
|
-
}
|
|
491
|
-
});
|
|
492
|
-
|
|
493
|
-
return annotationsWithPendingReview;
|
|
494
|
-
},
|
|
495
|
-
|
|
496
|
-
/**
|
|
497
|
-
* Check if the document was extracted correctly and is ready to be reviewed
|
|
498
|
-
*/
|
|
499
|
-
isDocumentReadyToBeReviewed: () => (document) => {
|
|
500
|
-
return document.status_data === 2 && document.labeling_available === 1;
|
|
501
|
-
},
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* Check if the document had an error during extraction
|
|
505
|
-
*/
|
|
506
|
-
documentHadErrorDuringExtraction: () => (document) => {
|
|
507
|
-
return document.status_data === 111;
|
|
508
|
-
},
|
|
509
|
-
|
|
510
|
-
/**
|
|
511
|
-
* check if the document has a dataset status of 'Training', 'Test' or 'Preparation'
|
|
512
|
-
* or if it is Ready Only / Reviewed
|
|
513
|
-
* and if so disable the option to edit the document
|
|
514
|
-
*/
|
|
515
|
-
documentCannotBeEdited:
|
|
516
|
-
(state) =>
|
|
517
|
-
(document = state.selectedDocument) => {
|
|
518
|
-
return (
|
|
519
|
-
document.dataset_status === 1 ||
|
|
520
|
-
document.dataset_status === 2 ||
|
|
521
|
-
document.dataset_status === 3 ||
|
|
522
|
-
document.is_reviewed
|
|
523
|
-
);
|
|
524
|
-
},
|
|
525
|
-
|
|
526
|
-
/**
|
|
527
|
-
* If automatic splitting is enabled for the project
|
|
528
|
-
*/
|
|
529
|
-
waitingForSplittingConfirmation: () => (document) => {
|
|
530
|
-
return document && document.status_data === 41;
|
|
531
|
-
},
|
|
532
|
-
|
|
533
|
-
/**
|
|
534
|
-
* Show the Smart Split switch or not
|
|
535
|
-
*/
|
|
536
|
-
documentHasProposedSplit: () => (document) => {
|
|
537
|
-
return document.proposed_split && document.proposed_split.length > 0;
|
|
538
|
-
},
|
|
539
|
-
|
|
540
|
-
/**
|
|
541
|
-
* Check the level of confidence of an annotation
|
|
542
|
-
*/
|
|
543
|
-
confidence: () => (annotation) => {
|
|
544
|
-
if (annotation) {
|
|
545
|
-
return annotation.confidence;
|
|
546
|
-
} else {
|
|
547
|
-
return null;
|
|
548
|
-
}
|
|
549
|
-
},
|
|
550
|
-
|
|
551
|
-
/**
|
|
552
|
-
* Check status of annotation
|
|
553
|
-
*/
|
|
554
|
-
notExtracted: () => (annotation) => {
|
|
555
|
-
if (annotation) {
|
|
556
|
-
return !annotation.span;
|
|
557
|
-
} else {
|
|
558
|
-
return true;
|
|
559
|
-
}
|
|
560
|
-
},
|
|
561
|
-
created: () => (annotation) => {
|
|
562
|
-
if (annotation) {
|
|
563
|
-
return (
|
|
564
|
-
annotation.created_by && !annotation.revised && annotation.is_correct
|
|
565
|
-
);
|
|
566
|
-
} else {
|
|
567
|
-
return null;
|
|
568
|
-
}
|
|
569
|
-
},
|
|
570
|
-
edited: () => (annotation) => {
|
|
571
|
-
if (annotation) {
|
|
572
|
-
if (annotation.offset_string !== annotation.offset_string_original) {
|
|
573
|
-
return true;
|
|
574
|
-
} else if (annotation.created_by) {
|
|
575
|
-
return true;
|
|
576
|
-
} else {
|
|
577
|
-
return false;
|
|
578
|
-
}
|
|
579
|
-
} else {
|
|
580
|
-
return null;
|
|
581
|
-
}
|
|
582
|
-
},
|
|
583
|
-
accepted: () => (annotation) => {
|
|
584
|
-
if (annotation) {
|
|
585
|
-
return annotation.revised && annotation.is_correct;
|
|
586
|
-
} else {
|
|
587
|
-
return null;
|
|
588
|
-
}
|
|
589
|
-
},
|
|
590
|
-
isNegative: () => (annotation) => {
|
|
591
|
-
if (annotation) {
|
|
592
|
-
return !annotation.is_correct && annotation.revised;
|
|
593
|
-
} else {
|
|
594
|
-
return null;
|
|
595
|
-
}
|
|
596
|
-
},
|
|
597
|
-
|
|
598
|
-
/**
|
|
599
|
-
* Check for user who created or revised the annotation
|
|
600
|
-
*/
|
|
601
|
-
getUser: () => (annotation) => {
|
|
602
|
-
if (annotation) {
|
|
603
|
-
if (annotation.created_by && !annotation.revised) {
|
|
604
|
-
// If the annotation was created but not yet revised
|
|
605
|
-
// we show who created it
|
|
606
|
-
return annotation.created_by;
|
|
607
|
-
} else if (annotation.revised && annotation.revised_by) {
|
|
608
|
-
return annotation.revised_by;
|
|
609
|
-
} else {
|
|
610
|
-
// If both revised_by and created_by are null, we don't show any user
|
|
611
|
-
return null;
|
|
612
|
-
}
|
|
613
|
-
} else {
|
|
614
|
-
return null;
|
|
615
|
-
}
|
|
616
|
-
},
|
|
617
|
-
|
|
618
|
-
/**
|
|
619
|
-
* Check if there is just one annotation set from a label set
|
|
620
|
-
*/
|
|
621
|
-
isOnlyMultipleAnnotationSet: (state) => (annotationSet) => {
|
|
622
|
-
const sameSets = state.annotationSets.filter(set => set.label_set.id === annotationSet.label_set.id);
|
|
623
|
-
|
|
624
|
-
return sameSets.length === 1 ? true : false;
|
|
625
|
-
},
|
|
626
|
-
|
|
627
|
-
/**
|
|
628
|
-
* Check if the annotation set can appear multiple times
|
|
629
|
-
*/
|
|
630
|
-
annotationSetCanBeMultiple: (_) => (annotationSet) => {
|
|
631
|
-
return annotationSet.label_set.has_multiple_annotation_sets;
|
|
632
|
-
},
|
|
633
|
-
|
|
634
|
-
/**
|
|
635
|
-
* Check if the annotation set has only empty labels
|
|
636
|
-
*/
|
|
637
|
-
annotationSetHasNoFilledLabels: (_) => (annotationSet) => {
|
|
638
|
-
const annotations = annotationSet.labels.flatMap(label => {
|
|
639
|
-
return label.annotations;
|
|
640
|
-
});
|
|
641
|
-
|
|
642
|
-
console.log(annotations);
|
|
643
|
-
|
|
644
|
-
return annotations.length === 0 ? true : false;
|
|
645
|
-
},
|
|
646
|
-
};
|
|
647
|
-
|
|
648
|
-
const actions = {
|
|
649
|
-
startLoading: ({ commit }) => {
|
|
650
|
-
commit("SET_LOADING", true);
|
|
651
|
-
},
|
|
652
|
-
endLoading: ({ commit }) => {
|
|
653
|
-
commit("SET_LOADING", false);
|
|
654
|
-
},
|
|
655
|
-
setDocId: ({ commit }, id) => {
|
|
656
|
-
commit("SET_PAGES", []);
|
|
657
|
-
commit("SET_DOC_ID", id);
|
|
658
|
-
},
|
|
659
|
-
setSidebarAnnotationSelected: ({ commit }, annotation) => {
|
|
660
|
-
commit("SET_ANNOTATION_SELECTED", annotation);
|
|
661
|
-
},
|
|
662
|
-
setAnnotationSets: ({ commit }, annotationSets) => {
|
|
663
|
-
commit("SET_ANNOTATION_SETS", annotationSets);
|
|
664
|
-
},
|
|
665
|
-
setEditAnnotation: (
|
|
666
|
-
{ commit },
|
|
667
|
-
{ id, index, label, labelSet, annotationSet }
|
|
668
|
-
) => {
|
|
669
|
-
const value = {
|
|
670
|
-
id,
|
|
671
|
-
index,
|
|
672
|
-
label,
|
|
673
|
-
labelSet,
|
|
674
|
-
annotationSet,
|
|
675
|
-
};
|
|
676
|
-
commit("SET_EDIT_ANNOTATION", value);
|
|
677
|
-
},
|
|
678
|
-
resetEditAnnotation: ({ commit }) => {
|
|
679
|
-
commit("RESET_EDIT_ANNOTATION");
|
|
680
|
-
},
|
|
681
|
-
setAnnotations: ({ commit }, annotations) => {
|
|
682
|
-
commit("SET_ANNOTATIONS", annotations);
|
|
683
|
-
},
|
|
684
|
-
setLabels: ({ commit }, labels) => {
|
|
685
|
-
commit("SET_LABELS", labels);
|
|
686
|
-
},
|
|
687
|
-
setPages: ({ commit }, pages) => {
|
|
688
|
-
commit("SET_PAGES", pages);
|
|
689
|
-
},
|
|
690
|
-
setSelectedDocument: ({ commit }, document) => {
|
|
691
|
-
commit("SET_SELECTED_DOCUMENT", document);
|
|
692
|
-
},
|
|
693
|
-
setPublicView: ({ commit }, publicView) => {
|
|
694
|
-
commit("SET_PUBLIC_VIEW", publicView);
|
|
695
|
-
},
|
|
696
|
-
startRecalculatingAnnotations: ({ commit }) => {
|
|
697
|
-
commit("SET_RECALCULATING_ANNOTATIONS", true);
|
|
698
|
-
},
|
|
699
|
-
endRecalculatingAnnotations: ({ commit }) => {
|
|
700
|
-
commit("SET_RECALCULATING_ANNOTATIONS", false);
|
|
701
|
-
},
|
|
702
|
-
setMissingAnnotations: ({ commit }, missingAnnotations) => {
|
|
703
|
-
commit("SET_MISSING_ANNOTATIONS", missingAnnotations);
|
|
704
|
-
},
|
|
705
|
-
setErrorMessage: ({ commit, dispatch }, message) => {
|
|
706
|
-
if (message) {
|
|
707
|
-
commit("SET_SHOW_ACTION_ERROR", true);
|
|
708
|
-
} else {
|
|
709
|
-
commit("SET_SHOW_ACTION_ERROR", false);
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
commit("SET_ERROR_MESSAGE", message);
|
|
713
|
-
|
|
714
|
-
dispatch("closeErrorMessage");
|
|
715
|
-
},
|
|
716
|
-
setDocumentError: ({ commit }, value) => {
|
|
717
|
-
commit("SET_DOCUMENT_ERROR", value);
|
|
718
|
-
},
|
|
719
|
-
setAnnotationsMarkedAsMissing: ({ commit }, annotations) => {
|
|
720
|
-
commit("SET_ANNOTATIONS_MARKED_AS_MISSING", annotations);
|
|
721
|
-
},
|
|
722
|
-
setErrorMessageWidth: ({ commit }, width) => {
|
|
723
|
-
commit("SET_ERROR_MESSAGE_WIDTH", width);
|
|
724
|
-
},
|
|
725
|
-
setHoveredAnnotationSet: ({ commit }, annotationSet) => {
|
|
726
|
-
commit("SET_HOVERED_ANNOTATION_SET", annotationSet);
|
|
727
|
-
},
|
|
728
|
-
setNewAcceptedAnnotations: ({ commit }, annotations) => {
|
|
729
|
-
commit("SET_NEW_ACCEPTED_ANNOTATIONS", annotations);
|
|
730
|
-
},
|
|
731
|
-
setSplittingSuggestions: ({ commit }, value) => {
|
|
732
|
-
commit("SET_SPLITTING_SUGGESTIONS", value);
|
|
733
|
-
},
|
|
734
|
-
|
|
735
|
-
/**
|
|
736
|
-
* Actions that use HTTP requests always return the axios promise,
|
|
737
|
-
* so they can be `await`ed (useful to set the `loading` status).
|
|
738
|
-
*/
|
|
739
|
-
fetchDocument: async (
|
|
740
|
-
{ commit, state, dispatch, rootState, getters },
|
|
741
|
-
pollDocumentList = false
|
|
742
|
-
) => {
|
|
743
|
-
let projectId = null;
|
|
744
|
-
let categoryId = null;
|
|
745
|
-
let isRecalculatingAnnotations = false;
|
|
746
|
-
|
|
747
|
-
const initialPage = 1;
|
|
748
|
-
|
|
749
|
-
dispatch("startLoading");
|
|
750
|
-
dispatch("display/updateCurrentPage", initialPage, {
|
|
751
|
-
root: true,
|
|
752
|
-
});
|
|
753
|
-
|
|
754
|
-
await HTTP.get(`documents/${state.documentId}/`)
|
|
755
|
-
.then(async (response) => {
|
|
756
|
-
if (response.data) {
|
|
757
|
-
const { labels, annotations, annotationSets } =
|
|
758
|
-
getters.processAnnotationSets(response.data.annotation_sets);
|
|
759
|
-
|
|
760
|
-
// load first page
|
|
761
|
-
if (response.data.pages.length > 0) {
|
|
762
|
-
dispatch("fetchDocumentPage", initialPage);
|
|
763
|
-
}
|
|
764
|
-
|
|
765
|
-
// set information on the store
|
|
766
|
-
commit("SET_ANNOTATION_SETS", annotationSets);
|
|
767
|
-
commit("SET_ANNOTATIONS", annotations);
|
|
768
|
-
commit("SET_LABELS", labels);
|
|
769
|
-
commit("SET_SELECTED_DOCUMENT", response.data);
|
|
770
|
-
|
|
771
|
-
if (response.data.project) {
|
|
772
|
-
projectId = response.data.project;
|
|
773
|
-
|
|
774
|
-
dispatch("project/setProjectId", projectId, {
|
|
775
|
-
root: true,
|
|
776
|
-
});
|
|
777
|
-
dispatch("project/fetchProjectDetails", projectId, {
|
|
778
|
-
root: true,
|
|
779
|
-
});
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
if (getters.documentHasProposedSplit(response.data)) {
|
|
783
|
-
commit("SET_SPLITTING_SUGGESTIONS", response.data.proposed_split);
|
|
784
|
-
}
|
|
785
|
-
|
|
786
|
-
categoryId = response.data.category;
|
|
787
|
-
// TODO: add this validation to a method
|
|
788
|
-
isRecalculatingAnnotations = response.data.labeling_available !== 1;
|
|
789
|
-
}
|
|
790
|
-
})
|
|
791
|
-
.catch((error) => {
|
|
792
|
-
console.log(error, "Could not fetch document details from the backend");
|
|
793
|
-
return;
|
|
794
|
-
});
|
|
795
|
-
|
|
796
|
-
if (!state.publicView) {
|
|
797
|
-
await dispatch("fetchMissingAnnotations");
|
|
798
|
-
|
|
799
|
-
await dispatch("project/fetchCurrentUser", null, {
|
|
800
|
-
root: true,
|
|
801
|
-
});
|
|
802
|
-
|
|
803
|
-
// Check if we first open the document dashboard or the edit mode
|
|
804
|
-
if (
|
|
805
|
-
!state.selectedDocument.category ||
|
|
806
|
-
(!state.selectedDocument.category_is_revised &&
|
|
807
|
-
!getters.documentHasCorrectAnnotations &&
|
|
808
|
-
state.missingAnnotations.length === 0)
|
|
809
|
-
) {
|
|
810
|
-
dispatch("edit/enableEditMode", null, {
|
|
811
|
-
root: true,
|
|
812
|
-
});
|
|
813
|
-
dispatch("edit/setRenameAndCategorize", true, { root: true });
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
if (projectId) {
|
|
817
|
-
await dispatch("category/fetchCategories", projectId, {
|
|
818
|
-
root: true,
|
|
819
|
-
});
|
|
820
|
-
|
|
821
|
-
// get list of documents not reviewed
|
|
822
|
-
await dispatch("project/fetchDocumentList", "is_reviewed=false", {
|
|
823
|
-
root: true,
|
|
824
|
-
});
|
|
825
|
-
}
|
|
826
|
-
if (categoryId && rootState.category.createAvailableListOfDocuments) {
|
|
827
|
-
await dispatch(
|
|
828
|
-
"category/createAvailableDocumentsList",
|
|
829
|
-
{
|
|
830
|
-
categoryId,
|
|
831
|
-
user: rootState.project.currentUser.username,
|
|
832
|
-
poll: pollDocumentList,
|
|
833
|
-
},
|
|
834
|
-
{
|
|
835
|
-
root: true,
|
|
836
|
-
}
|
|
837
|
-
);
|
|
838
|
-
}
|
|
839
|
-
}
|
|
840
|
-
if (isRecalculatingAnnotations) {
|
|
841
|
-
commit("SET_RECALCULATING_ANNOTATIONS", true);
|
|
842
|
-
dispatch("pollDocumentEndpoint");
|
|
843
|
-
}
|
|
844
|
-
dispatch("endLoading");
|
|
845
|
-
},
|
|
846
|
-
|
|
847
|
-
// Get document page data
|
|
848
|
-
fetchDocumentPage: ({ commit, state }, page) => {
|
|
849
|
-
return HTTP.get(`documents/${state.documentId}/pages/${page}/`)
|
|
850
|
-
.then((response) => {
|
|
851
|
-
commit("ADD_PAGE", response.data);
|
|
852
|
-
})
|
|
853
|
-
.catch((error) => {
|
|
854
|
-
console.log(error);
|
|
855
|
-
});
|
|
856
|
-
},
|
|
857
|
-
|
|
858
|
-
setDocumentAnnotationSelected: (
|
|
859
|
-
{ commit },
|
|
860
|
-
{ annotation, label, span, scrollTo = false }
|
|
861
|
-
) => {
|
|
862
|
-
const value = {
|
|
863
|
-
scrollTo,
|
|
864
|
-
id: annotation.id,
|
|
865
|
-
span,
|
|
866
|
-
page: span.page_index + 1,
|
|
867
|
-
labelName: label ? label.name : "",
|
|
868
|
-
};
|
|
869
|
-
commit("SET_DOCUMENT_ANNOTATION_SELECTED", value);
|
|
870
|
-
},
|
|
871
|
-
|
|
872
|
-
scrollToDocumentAnnotationSelected: ({ commit }) => {
|
|
873
|
-
commit("SET_DOCUMENT_ANNOTATION_SCROLL", true);
|
|
874
|
-
},
|
|
875
|
-
|
|
876
|
-
disableDocumentAnnotationSelected: ({ commit }) => {
|
|
877
|
-
commit("SET_DOCUMENT_ANNOTATION_SELECTED", null);
|
|
878
|
-
},
|
|
879
|
-
|
|
880
|
-
createAnnotation: (
|
|
881
|
-
{ commit, getters, dispatch },
|
|
882
|
-
{ annotation, negativeAnnotationId }
|
|
883
|
-
) => {
|
|
884
|
-
return new Promise((resolve, reject) => {
|
|
885
|
-
HTTP.post(`/annotations/`, annotation)
|
|
886
|
-
.then(async (response) => {
|
|
887
|
-
if (response.status === 201) {
|
|
888
|
-
await dispatch("fetchMissingAnnotations");
|
|
889
|
-
|
|
890
|
-
if (!getters.annotationSetExists(response.data.annotation_set)) {
|
|
891
|
-
const documentData = await dispatch("fetchDocumentData");
|
|
892
|
-
if (documentData && documentData.annotation_sets) {
|
|
893
|
-
const { labels, annotations, annotationSets } =
|
|
894
|
-
getters.processAnnotationSets(documentData.annotation_sets);
|
|
895
|
-
commit("SET_ANNOTATION_SETS", annotationSets);
|
|
896
|
-
commit("SET_ANNOTATIONS", annotations);
|
|
897
|
-
commit("SET_LABELS", labels);
|
|
898
|
-
}
|
|
899
|
-
} else {
|
|
900
|
-
commit("ADD_ANNOTATION", response.data);
|
|
901
|
-
if (negativeAnnotationId) {
|
|
902
|
-
commit("DELETE_ANNOTATION", negativeAnnotationId);
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
|
|
906
|
-
resolve(response);
|
|
907
|
-
}
|
|
908
|
-
})
|
|
909
|
-
.catch((error) => {
|
|
910
|
-
reject(error.response);
|
|
911
|
-
console.log(error);
|
|
912
|
-
});
|
|
913
|
-
});
|
|
914
|
-
},
|
|
915
|
-
|
|
916
|
-
updateAnnotation: (
|
|
917
|
-
{ commit, getters, dispatch },
|
|
918
|
-
{ updatedValues, annotationId }
|
|
919
|
-
) => {
|
|
920
|
-
commit("SET_NEW_ACCEPTED_ANNOTATIONS", [annotationId]);
|
|
921
|
-
|
|
922
|
-
return new Promise((resolve, reject) => {
|
|
923
|
-
HTTP.patch(`/annotations/${annotationId}/`, updatedValues)
|
|
924
|
-
.then(async (response) => {
|
|
925
|
-
if (response.status === 200) {
|
|
926
|
-
commit("UPDATE_ANNOTATION", response.data);
|
|
927
|
-
commit("SET_NEW_ACCEPTED_ANNOTATIONS", null);
|
|
928
|
-
|
|
929
|
-
resolve(true);
|
|
930
|
-
}
|
|
931
|
-
})
|
|
932
|
-
.catch((error) => {
|
|
933
|
-
reject(error.response);
|
|
934
|
-
console.log(error);
|
|
935
|
-
});
|
|
936
|
-
});
|
|
937
|
-
},
|
|
938
|
-
|
|
939
|
-
deleteAnnotation: ({ commit, getters }, { annotationId, annotationSet }) => {
|
|
940
|
-
return new Promise((resolve, reject) => {
|
|
941
|
-
HTTP.delete(`/annotations/${annotationId}/`)
|
|
942
|
-
.then(async (response) => {
|
|
943
|
-
if (response.status === 204) {
|
|
944
|
-
commit("DELETE_ANNOTATION", annotationId);
|
|
945
|
-
|
|
946
|
-
// Check if the deleted annotation was the last one in a multiple annotation set
|
|
947
|
-
// and if the annotation set has no annotations
|
|
948
|
-
if (annotationSet && getters.annotationSetCanBeMultiple(annotationSet) && getters.annotationSetHasNoFilledLabels(annotationSet)) {
|
|
949
|
-
// Check if there is still 1 or more multiple annotation sets for the same label set
|
|
950
|
-
if (getters.isOnlyMultipleAnnotationSet(annotationSet)) {
|
|
951
|
-
commit("UPDATE_ANNOTATION_SET", annotationSet);
|
|
952
|
-
} else {
|
|
953
|
-
commit("DELETE_ANNOTATION_SET", annotationSet);
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
resolve(true);
|
|
958
|
-
}
|
|
959
|
-
})
|
|
960
|
-
.catch((error) => {
|
|
961
|
-
reject(error.response);
|
|
962
|
-
console.log(error);
|
|
963
|
-
});
|
|
964
|
-
});
|
|
965
|
-
},
|
|
966
|
-
|
|
967
|
-
updateDocument: ({ commit, state, getters, dispatch }, updatedDocument) => {
|
|
968
|
-
return new Promise((resolve, reject) => {
|
|
969
|
-
HTTP.patch(`/documents/${state.documentId}/`, updatedDocument)
|
|
970
|
-
.then((response) => {
|
|
971
|
-
if (response.status === 200) {
|
|
972
|
-
if (updatedDocument.data_file_name) {
|
|
973
|
-
// if the only change was the file name, don't reload the page
|
|
974
|
-
// only update the file name for the selectedDocument
|
|
975
|
-
commit("UPDATE_FILE_NAME", response.data.data_file_name);
|
|
976
|
-
} else {
|
|
977
|
-
commit("SET_SELECTED_DOCUMENT", response.data);
|
|
978
|
-
|
|
979
|
-
dispatch("pollDocumentEndpoint");
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
resolve(true);
|
|
983
|
-
}
|
|
984
|
-
})
|
|
985
|
-
.catch((error) => {
|
|
986
|
-
console.log(error);
|
|
987
|
-
// check if review error
|
|
988
|
-
if (
|
|
989
|
-
error.response &&
|
|
990
|
-
error.response.request &&
|
|
991
|
-
error.response.request.response
|
|
992
|
-
) {
|
|
993
|
-
const is_reviewed = JSON.parse(error.request.response).is_reviewed;
|
|
994
|
-
if (is_reviewed && is_reviewed.length > 0) {
|
|
995
|
-
const errorData = {
|
|
996
|
-
data: [...is_reviewed],
|
|
997
|
-
};
|
|
998
|
-
reject(errorData);
|
|
999
|
-
return;
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
reject(error.response);
|
|
1003
|
-
});
|
|
1004
|
-
});
|
|
1005
|
-
},
|
|
1006
|
-
|
|
1007
|
-
fetchMissingAnnotations: ({ commit, state, getters }) => {
|
|
1008
|
-
return new Promise((resolve, reject) => {
|
|
1009
|
-
return HTTP.get(
|
|
1010
|
-
`/missing-annotations/?document=${state.documentId}&limit=100`
|
|
1011
|
-
)
|
|
1012
|
-
.then((response) => {
|
|
1013
|
-
commit("SET_MISSING_ANNOTATIONS", response.data.results);
|
|
1014
|
-
resolve(true);
|
|
1015
|
-
})
|
|
1016
|
-
.catch((error) => {
|
|
1017
|
-
reject(error.response);
|
|
1018
|
-
console.log(error);
|
|
1019
|
-
});
|
|
1020
|
-
});
|
|
1021
|
-
},
|
|
1022
|
-
|
|
1023
|
-
addMissingAnnotations: ({ commit, getters }, missingAnnotations) => {
|
|
1024
|
-
return new Promise((resolve, reject) => {
|
|
1025
|
-
HTTP.post(`/missing-annotations/`, missingAnnotations)
|
|
1026
|
-
.then(async (response) => {
|
|
1027
|
-
if (response.status === 201) {
|
|
1028
|
-
commit("SET_ANNOTATIONS_MARKED_AS_MISSING", null);
|
|
1029
|
-
commit("ADD_MISSING_ANNOTATIONS", response.data);
|
|
1030
|
-
}
|
|
1031
|
-
|
|
1032
|
-
resolve(response);
|
|
1033
|
-
})
|
|
1034
|
-
.catch((error) => {
|
|
1035
|
-
reject(error.response);
|
|
1036
|
-
console.log(error);
|
|
1037
|
-
});
|
|
1038
|
-
});
|
|
1039
|
-
},
|
|
1040
|
-
|
|
1041
|
-
deleteMissingAnnotation: ({ commit, getters }, id) => {
|
|
1042
|
-
return new Promise((resolve, reject) => {
|
|
1043
|
-
return HTTP.delete(`/missing-annotations/${id}/`)
|
|
1044
|
-
.then((response) => {
|
|
1045
|
-
if (response.status === 204) {
|
|
1046
|
-
commit("DELETE_MISSING_ANNOTATION", id);
|
|
1047
|
-
resolve(true);
|
|
1048
|
-
}
|
|
1049
|
-
})
|
|
1050
|
-
.catch((error) => {
|
|
1051
|
-
reject(error.response);
|
|
1052
|
-
console.log(error);
|
|
1053
|
-
});
|
|
1054
|
-
});
|
|
1055
|
-
},
|
|
1056
|
-
|
|
1057
|
-
updateMultipleAnnotations: ({ state, commit }, annotations) => {
|
|
1058
|
-
commit("SET_NEW_ACCEPTED_ANNOTATIONS", annotations.ids);
|
|
1059
|
-
|
|
1060
|
-
return new Promise((resolve, reject) => {
|
|
1061
|
-
return HTTP.patch(
|
|
1062
|
-
`documents/${state.documentId}/update-annotations/`,
|
|
1063
|
-
annotations
|
|
1064
|
-
)
|
|
1065
|
-
.then((response) => {
|
|
1066
|
-
if (response.status === 200) {
|
|
1067
|
-
response.data.map((annotation) => {
|
|
1068
|
-
commit("UPDATE_ANNOTATION", annotation);
|
|
1069
|
-
});
|
|
1070
|
-
commit("SET_NEW_ACCEPTED_ANNOTATIONS", null);
|
|
1071
|
-
resolve(true);
|
|
1072
|
-
}
|
|
1073
|
-
})
|
|
1074
|
-
.catch((error) => {
|
|
1075
|
-
console.log(error);
|
|
1076
|
-
reject(error.response);
|
|
1077
|
-
});
|
|
1078
|
-
});
|
|
1079
|
-
},
|
|
1080
|
-
|
|
1081
|
-
fetchDocumentStatus: ({ state, getters }) => {
|
|
1082
|
-
return new Promise((resolve, reject) => {
|
|
1083
|
-
return HTTP.get(
|
|
1084
|
-
`documents/${state.documentId}/?fields=status_data,labeling_available`
|
|
1085
|
-
)
|
|
1086
|
-
.then((response) => {
|
|
1087
|
-
if (
|
|
1088
|
-
getters.isDocumentReadyToBeReviewed(response.data) ||
|
|
1089
|
-
getters.waitingForSplittingConfirmation(response.data)
|
|
1090
|
-
) {
|
|
1091
|
-
// ready or has splitting suggestions
|
|
1092
|
-
return resolve(true);
|
|
1093
|
-
} else if (getters.documentHadErrorDuringExtraction(response.data)) {
|
|
1094
|
-
// error
|
|
1095
|
-
return reject();
|
|
1096
|
-
} else {
|
|
1097
|
-
// not yet ready
|
|
1098
|
-
return resolve(false);
|
|
1099
|
-
}
|
|
1100
|
-
})
|
|
1101
|
-
.catch((error) => {
|
|
1102
|
-
reject(error.response);
|
|
1103
|
-
console.log(error);
|
|
1104
|
-
});
|
|
1105
|
-
});
|
|
1106
|
-
},
|
|
1107
|
-
|
|
1108
|
-
// Get document data
|
|
1109
|
-
fetchDocumentData: ({ state }) => {
|
|
1110
|
-
return new Promise((resolve, reject) => {
|
|
1111
|
-
HTTP.get(`documents/${state.documentId}/`)
|
|
1112
|
-
.then((response) => {
|
|
1113
|
-
return resolve(response.data);
|
|
1114
|
-
})
|
|
1115
|
-
.catch((error) => {
|
|
1116
|
-
reject(error);
|
|
1117
|
-
console.log(error);
|
|
1118
|
-
});
|
|
1119
|
-
});
|
|
1120
|
-
},
|
|
1121
|
-
|
|
1122
|
-
// Poll Document endpoint to know if the Document is ready to be reviewed
|
|
1123
|
-
// or even if there was an error during the extraction
|
|
1124
|
-
pollDocumentEndpoint: ({ dispatch }) => {
|
|
1125
|
-
return dispatch("fetchDocumentStatus")
|
|
1126
|
-
.then((ready) => {
|
|
1127
|
-
if (ready) {
|
|
1128
|
-
// Stop document recalculating annotations
|
|
1129
|
-
dispatch("endRecalculatingAnnotations");
|
|
1130
|
-
dispatch("fetchDocument");
|
|
1131
|
-
} else {
|
|
1132
|
-
sleep(documentPollDuration);
|
|
1133
|
-
dispatch("pollDocumentEndpoint");
|
|
1134
|
-
}
|
|
1135
|
-
})
|
|
1136
|
-
.catch((error) => {
|
|
1137
|
-
dispatch("setDocumentError", true);
|
|
1138
|
-
console.log(error);
|
|
1139
|
-
});
|
|
1140
|
-
},
|
|
1141
|
-
|
|
1142
|
-
createErrorMessage: (
|
|
1143
|
-
{ commit, dispatch },
|
|
1144
|
-
{ error, serverErrorMessage, defaultErrorMessage }
|
|
1145
|
-
) => {
|
|
1146
|
-
// check type of error
|
|
1147
|
-
if (error && error.status >= 500 && error.status < 600) {
|
|
1148
|
-
dispatch("setErrorMessage", serverErrorMessage);
|
|
1149
|
-
commit("SET_SERVER_ERROR", true);
|
|
1150
|
-
} else if (error.data && error.data.length > 0) {
|
|
1151
|
-
dispatch("setErrorMessage", error.data[0]);
|
|
1152
|
-
} else {
|
|
1153
|
-
dispatch("setErrorMessage", defaultErrorMessage);
|
|
1154
|
-
}
|
|
1155
|
-
},
|
|
1156
|
-
|
|
1157
|
-
closeErrorMessage: ({ commit }) => {
|
|
1158
|
-
setTimeout(() => {
|
|
1159
|
-
commit("SET_ERROR_MESSAGE", null);
|
|
1160
|
-
commit("SET_SHOW_ACTION_ERROR", false);
|
|
1161
|
-
commit("SET_SERVER_ERROR", false);
|
|
1162
|
-
}, 5000);
|
|
1163
|
-
},
|
|
1164
|
-
|
|
1165
|
-
contactSupport: ({ rootState }, error) => {
|
|
1166
|
-
const url = "https://konfuzio.com/support/";
|
|
1167
|
-
const params = `project=${rootState.project.projectId}&email=${rootState.project.currentUser.username}&issue=${error}`;
|
|
1168
|
-
const fullUrl = `${url}?${params}`;
|
|
1169
|
-
|
|
1170
|
-
window.open(fullUrl, "_blank");
|
|
1171
|
-
},
|
|
1172
|
-
|
|
1173
|
-
changeCurrentDocument: ({ commit, state, dispatch }, newDocumentId) => {
|
|
1174
|
-
// reset splitting suggestions
|
|
1175
|
-
if (state.splittingSuggestions) {
|
|
1176
|
-
commit("SET_SPLITTING_SUGGESTIONS", null);
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
if (getURLQueryParam("document") || getURLPath("d")) {
|
|
1180
|
-
navigateToNewDocumentURL(state.selectedDocument.id, newDocumentId);
|
|
1181
|
-
} else {
|
|
1182
|
-
commit("SET_DOC_ID", newDocumentId);
|
|
1183
|
-
dispatch("fetchDocument");
|
|
1184
|
-
}
|
|
1185
|
-
},
|
|
1186
|
-
};
|
|
1187
|
-
|
|
1188
|
-
const mutations = {
|
|
1189
|
-
SET_LOADING: (state, loading) => {
|
|
1190
|
-
state.loading = loading;
|
|
1191
|
-
},
|
|
1192
|
-
SET_DOC_ID: (state, id) => {
|
|
1193
|
-
if (id !== state.documentId) {
|
|
1194
|
-
state.documentId = id;
|
|
1195
|
-
}
|
|
1196
|
-
},
|
|
1197
|
-
ADD_ANNOTATION: (state, annotation) => {
|
|
1198
|
-
state.annotations.push(annotation);
|
|
1199
|
-
state.annotationSets.map((annotationSet) => {
|
|
1200
|
-
if (
|
|
1201
|
-
annotation.annotation_set === annotationSet.id &&
|
|
1202
|
-
annotation.label_set &&
|
|
1203
|
-
annotationSet.label_set.id === annotation.label_set.id
|
|
1204
|
-
) {
|
|
1205
|
-
annotationSet.labels.map((label) => {
|
|
1206
|
-
if (annotation.label && annotation.label.id === label.id) {
|
|
1207
|
-
const exists = label.annotations.find(
|
|
1208
|
-
(existingAnnotation) => existingAnnotation.id === annotation.id
|
|
1209
|
-
);
|
|
1210
|
-
|
|
1211
|
-
if (!exists) {
|
|
1212
|
-
label.annotations.push(annotation);
|
|
1213
|
-
return;
|
|
1214
|
-
}
|
|
1215
|
-
}
|
|
1216
|
-
});
|
|
1217
|
-
}
|
|
1218
|
-
});
|
|
1219
|
-
},
|
|
1220
|
-
UPDATE_ANNOTATION: (state, annotation) => {
|
|
1221
|
-
const indexOfAnnotationInAnnotations = state.annotations.findIndex(
|
|
1222
|
-
(existingAnnotation) => existingAnnotation.id === annotation.id
|
|
1223
|
-
);
|
|
1224
|
-
if (indexOfAnnotationInAnnotations > -1) {
|
|
1225
|
-
state.annotations.splice(indexOfAnnotationInAnnotations, 1, annotation);
|
|
1226
|
-
}
|
|
1227
|
-
let updatedAnnotation = false;
|
|
1228
|
-
state.annotationSets.forEach((annotationSet) => {
|
|
1229
|
-
if (updatedAnnotation) {
|
|
1230
|
-
return;
|
|
1231
|
-
}
|
|
1232
|
-
annotationSet.labels.forEach((label) => {
|
|
1233
|
-
const indexOfAnnotationAnnotationSets = label.annotations.findIndex(
|
|
1234
|
-
(existingAnnotation) => existingAnnotation.id === annotation.id
|
|
1235
|
-
);
|
|
1236
|
-
if (indexOfAnnotationAnnotationSets > -1) {
|
|
1237
|
-
// checks if an annotation label was changed and add it to the new label
|
|
1238
|
-
if (annotation.label && annotation.label.id !== label.id) {
|
|
1239
|
-
label.annotations.splice(indexOfAnnotationAnnotationSets, 1);
|
|
1240
|
-
|
|
1241
|
-
const labelToAdd = annotationSet.labels.find(
|
|
1242
|
-
(labelToAdd) => labelToAdd.id === annotation.label.id
|
|
1243
|
-
);
|
|
1244
|
-
labelToAdd.annotations.push(annotation);
|
|
1245
|
-
} else {
|
|
1246
|
-
label.annotations.splice(
|
|
1247
|
-
indexOfAnnotationAnnotationSets,
|
|
1248
|
-
1,
|
|
1249
|
-
annotation
|
|
1250
|
-
);
|
|
1251
|
-
}
|
|
1252
|
-
updatedAnnotation = true;
|
|
1253
|
-
return;
|
|
1254
|
-
}
|
|
1255
|
-
});
|
|
1256
|
-
});
|
|
1257
|
-
},
|
|
1258
|
-
DELETE_ANNOTATION: (state, annotationId) => {
|
|
1259
|
-
const indexOfAnnotationToDelete = state.annotations.findIndex(
|
|
1260
|
-
(existingAnnotation) => existingAnnotation.id === annotationId
|
|
1261
|
-
);
|
|
1262
|
-
if (indexOfAnnotationToDelete > -1) {
|
|
1263
|
-
state.annotations.splice(indexOfAnnotationToDelete, 1);
|
|
1264
|
-
}
|
|
1265
|
-
let deleted = false;
|
|
1266
|
-
state.annotationSets.forEach((annotationSet) => {
|
|
1267
|
-
if (deleted) {
|
|
1268
|
-
return;
|
|
1269
|
-
}
|
|
1270
|
-
annotationSet.labels.forEach((label) => {
|
|
1271
|
-
const indexOfAnnotationInLabelToDelete = label.annotations.findIndex(
|
|
1272
|
-
(existingAnnotation) => existingAnnotation.id === annotationId
|
|
1273
|
-
);
|
|
1274
|
-
if (indexOfAnnotationInLabelToDelete > -1) {
|
|
1275
|
-
label.annotations.splice(indexOfAnnotationInLabelToDelete, 1);
|
|
1276
|
-
deleted = true;
|
|
1277
|
-
return;
|
|
1278
|
-
}
|
|
1279
|
-
});
|
|
1280
|
-
});
|
|
1281
|
-
},
|
|
1282
|
-
SET_ANNOTATIONS: (state, annotations) => {
|
|
1283
|
-
state.annotations = annotations;
|
|
1284
|
-
},
|
|
1285
|
-
SET_ANNOTATION_SETS: (state, annotationSets) => {
|
|
1286
|
-
state.annotationSets = annotationSets;
|
|
1287
|
-
},
|
|
1288
|
-
DELETE_ANNOTATION_SET: (state, annotationSet) => {
|
|
1289
|
-
const indexOfSetToDelete = state.annotationSets.findIndex(
|
|
1290
|
-
(existingAnnotationSet) => existingAnnotationSet.id === annotationSet.id
|
|
1291
|
-
);
|
|
1292
|
-
|
|
1293
|
-
if (indexOfSetToDelete === -1) return;
|
|
1294
|
-
|
|
1295
|
-
state.annotationSets.splice(indexOfSetToDelete, 1);
|
|
1296
|
-
},
|
|
1297
|
-
UPDATE_ANNOTATION_SET: (state, annotationSet) => {
|
|
1298
|
-
const indexOfExistingAnnotationSet = state.annotationSets.findIndex(
|
|
1299
|
-
(existingAnnotationSet) => existingAnnotationSet.id === annotationSet.id
|
|
1300
|
-
);
|
|
1301
|
-
|
|
1302
|
-
if (indexOfExistingAnnotationSet === -1) return;
|
|
1303
|
-
|
|
1304
|
-
const updatedSet = { ...annotationSet, id: null };
|
|
1305
|
-
|
|
1306
|
-
state.annotationSets.splice(indexOfExistingAnnotationSet, 1, updatedSet);
|
|
1307
|
-
},
|
|
1308
|
-
SET_LABELS: (state, labels) => {
|
|
1309
|
-
state.labels = labels;
|
|
1310
|
-
},
|
|
1311
|
-
SET_ANNOTATION_SELECTED: (state, annotation) => {
|
|
1312
|
-
state.sidebarAnnotationSelected = annotation;
|
|
1313
|
-
},
|
|
1314
|
-
SET_EDIT_ANNOTATION: (state, editAnnotation) => {
|
|
1315
|
-
state.editAnnotation = editAnnotation;
|
|
1316
|
-
},
|
|
1317
|
-
RESET_EDIT_ANNOTATION: (state) => {
|
|
1318
|
-
state.editAnnotation = null;
|
|
1319
|
-
},
|
|
1320
|
-
ADD_PAGE: (state, page) => {
|
|
1321
|
-
// if we already have the page in the state, update it in
|
|
1322
|
-
// the pages array instead of creating a new one
|
|
1323
|
-
const existingPageIndex = state.pages.findIndex(
|
|
1324
|
-
(p) => p.number === page.number
|
|
1325
|
-
);
|
|
1326
|
-
if (existingPageIndex === -1) {
|
|
1327
|
-
state.pages.push(page);
|
|
1328
|
-
} else {
|
|
1329
|
-
state.pages[existingPageIndex] = page;
|
|
1330
|
-
}
|
|
1331
|
-
},
|
|
1332
|
-
SET_PAGES: (state, pages) => {
|
|
1333
|
-
state.pages = pages;
|
|
1334
|
-
},
|
|
1335
|
-
SET_DOCUMENT_ANNOTATION_SELECTED: (state, documentAnnotationSelected) => {
|
|
1336
|
-
state.documentAnnotationSelected = documentAnnotationSelected;
|
|
1337
|
-
},
|
|
1338
|
-
SET_DOCUMENT_ANNOTATION_SCROLL: (state, scrollTo) => {
|
|
1339
|
-
if (state.documentAnnotationSelected) {
|
|
1340
|
-
state.documentAnnotationSelected.scrollTo = scrollTo;
|
|
1341
|
-
}
|
|
1342
|
-
},
|
|
1343
|
-
SET_SELECTED_DOCUMENT: (state, document) => {
|
|
1344
|
-
state.selectedDocument = document;
|
|
1345
|
-
|
|
1346
|
-
// this is to handle cache when a document is edited or changed
|
|
1347
|
-
if (state.selectedDocument) {
|
|
1348
|
-
state.selectedDocument.downloaded_at = Date.now();
|
|
1349
|
-
}
|
|
1350
|
-
},
|
|
1351
|
-
SET_RECALCULATING_ANNOTATIONS: (state, recalculatingAnnotations) => {
|
|
1352
|
-
state.recalculatingAnnotations = recalculatingAnnotations;
|
|
1353
|
-
},
|
|
1354
|
-
SET_MISSING_ANNOTATIONS: (state, missingAnnotations) => {
|
|
1355
|
-
state.missingAnnotations = missingAnnotations;
|
|
1356
|
-
},
|
|
1357
|
-
ADD_MISSING_ANNOTATIONS: (state, annotations) => {
|
|
1358
|
-
if (annotations && annotations.length > 0) {
|
|
1359
|
-
annotations.map((annotation) => {
|
|
1360
|
-
// check if already in missingAnnotations
|
|
1361
|
-
const found = state.missingAnnotations.find(
|
|
1362
|
-
(missingAnnotation) => missingAnnotation.id === annotation.id
|
|
1363
|
-
);
|
|
1364
|
-
|
|
1365
|
-
if (found) {
|
|
1366
|
-
const indexOfAnnotation = state.missingAnnotations.findIndex(
|
|
1367
|
-
(missingAnnotation) => missingAnnotation.id === annotation.id
|
|
1368
|
-
);
|
|
1369
|
-
|
|
1370
|
-
if (indexOfAnnotation > -1) {
|
|
1371
|
-
state.missingAnnotations.splice(indexOfAnnotation, 1, annotation);
|
|
1372
|
-
}
|
|
1373
|
-
} else {
|
|
1374
|
-
state.missingAnnotations.push(annotation);
|
|
1375
|
-
}
|
|
1376
|
-
});
|
|
1377
|
-
} else {
|
|
1378
|
-
state.missingAnnotations.push(annotations);
|
|
1379
|
-
}
|
|
1380
|
-
},
|
|
1381
|
-
DELETE_MISSING_ANNOTATION: (state, id) => {
|
|
1382
|
-
const indexOfAnnotationToDelete = state.missingAnnotations.findIndex(
|
|
1383
|
-
(annotation) => annotation.id === id
|
|
1384
|
-
);
|
|
1385
|
-
|
|
1386
|
-
if (indexOfAnnotationToDelete > -1) {
|
|
1387
|
-
state.missingAnnotations.splice(indexOfAnnotationToDelete, 1);
|
|
1388
|
-
}
|
|
1389
|
-
},
|
|
1390
|
-
SET_SHOW_ACTION_ERROR: (state, value) => {
|
|
1391
|
-
state.showActionError = value;
|
|
1392
|
-
},
|
|
1393
|
-
SET_ERROR_MESSAGE: (state, message) => {
|
|
1394
|
-
state.errorMessage = message;
|
|
1395
|
-
},
|
|
1396
|
-
SET_DOCUMENT_ERROR: (state, value) => {
|
|
1397
|
-
state.showDocumentError = value;
|
|
1398
|
-
},
|
|
1399
|
-
SET_ANNOTATIONS_MARKED_AS_MISSING: (state, annotations) => {
|
|
1400
|
-
state.annotationsMarkedAsMissing = annotations;
|
|
1401
|
-
},
|
|
1402
|
-
SET_ERROR_MESSAGE_WIDTH: (state, width) => {
|
|
1403
|
-
state.errorMessageWidth = width;
|
|
1404
|
-
},
|
|
1405
|
-
SET_PUBLIC_VIEW: (state, value) => {
|
|
1406
|
-
state.publicView = value;
|
|
1407
|
-
},
|
|
1408
|
-
SET_DOCUMENT_IS_READY: (state, value) => {
|
|
1409
|
-
state.documentIsReady = value;
|
|
1410
|
-
},
|
|
1411
|
-
SET_DOCUMENT_HAS_ERROR: (state, value) => {
|
|
1412
|
-
state.documentHasError = value;
|
|
1413
|
-
},
|
|
1414
|
-
SET_HOVERED_ANNOTATION_SET: (state, hoveredAnnotationSet) => {
|
|
1415
|
-
state.hoveredAnnotationSet = hoveredAnnotationSet;
|
|
1416
|
-
},
|
|
1417
|
-
SET_NEW_ACCEPTED_ANNOTATIONS: (state, annotations) => {
|
|
1418
|
-
state.newAcceptedAnnotations = annotations;
|
|
1419
|
-
},
|
|
1420
|
-
SET_SERVER_ERROR: (state, value) => {
|
|
1421
|
-
state.serverError = value;
|
|
1422
|
-
},
|
|
1423
|
-
|
|
1424
|
-
UPDATE_FILE_NAME: (state, value) => {
|
|
1425
|
-
state.selectedDocument.data_file_name = value;
|
|
1426
|
-
},
|
|
1427
|
-
SET_SPLITTING_SUGGESTIONS: (state, array) => {
|
|
1428
|
-
state.splittingSuggestions = array;
|
|
1429
|
-
},
|
|
1430
|
-
};
|
|
1431
|
-
|
|
1432
|
-
export default {
|
|
1433
|
-
namespaced: true,
|
|
1434
|
-
state,
|
|
1435
|
-
getters,
|
|
1436
|
-
actions,
|
|
1437
|
-
mutations,
|
|
1438
|
-
};
|
|
1
|
+
import myImports from "../api";
|
|
2
|
+
import { MULTI_ANN_TABLE_FEATURE } from "../constants";
|
|
3
|
+
import {
|
|
4
|
+
sleep,
|
|
5
|
+
getURLQueryParam,
|
|
6
|
+
navigateToNewDocumentURL,
|
|
7
|
+
getURLPath,
|
|
8
|
+
} from "../utils/utils";
|
|
9
|
+
|
|
10
|
+
const HTTP = myImports.HTTP;
|
|
11
|
+
const documentPollDuration = 1000;
|
|
12
|
+
export const table_reference_api = "api.v3.dvui.table";
|
|
13
|
+
|
|
14
|
+
const state = {
|
|
15
|
+
loading: true,
|
|
16
|
+
pages: [],
|
|
17
|
+
annotationSets: null,
|
|
18
|
+
annotations: null,
|
|
19
|
+
labels: [],
|
|
20
|
+
documentId: process.env.VUE_APP_DOCUMENT_ID,
|
|
21
|
+
sidebarAnnotationSelected: null,
|
|
22
|
+
documentAnnotationSelected: null,
|
|
23
|
+
selectedDocument: null,
|
|
24
|
+
recalculatingAnnotations: false,
|
|
25
|
+
editAnnotation: null,
|
|
26
|
+
missingAnnotations: [],
|
|
27
|
+
publicView: true,
|
|
28
|
+
showActionError: false,
|
|
29
|
+
errorMessage: null,
|
|
30
|
+
showDocumentError: false,
|
|
31
|
+
annotationsMarkedAsMissing: null,
|
|
32
|
+
errorMessageWidth: null,
|
|
33
|
+
hoveredAnnotationSet: null,
|
|
34
|
+
newAcceptedAnnotations: null,
|
|
35
|
+
serverError: false,
|
|
36
|
+
splittingSuggestions: null,
|
|
37
|
+
enableGroupingFeature: true,
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const getters = {
|
|
41
|
+
/**
|
|
42
|
+
* Get entities inside a box
|
|
43
|
+
*/
|
|
44
|
+
entitiesOnSelection: (state) => (box, page) => {
|
|
45
|
+
return page.entities.filter(
|
|
46
|
+
(entity) =>
|
|
47
|
+
box.x0 <= entity.x0 &&
|
|
48
|
+
box.x1 >= entity.x1 &&
|
|
49
|
+
box.y0 <= entity.y0 &&
|
|
50
|
+
box.y1 >= entity.y1
|
|
51
|
+
);
|
|
52
|
+
},
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Number of pages. If the pages array doesn't exist yet, return 0.
|
|
56
|
+
*/
|
|
57
|
+
pageCount: (state) => {
|
|
58
|
+
if (state.selectedDocument.pages) {
|
|
59
|
+
return state.selectedDocument.pages.length;
|
|
60
|
+
}
|
|
61
|
+
return 0;
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Returns the current page
|
|
66
|
+
*/
|
|
67
|
+
pageSelected: (state, _, rootState) => {
|
|
68
|
+
if (state.pages) {
|
|
69
|
+
return state.pages[rootState.display.currentPage - 1];
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Returns a page in the given index
|
|
76
|
+
*/
|
|
77
|
+
pageAtIndex: (state) => (index) => {
|
|
78
|
+
if (state.selectedDocument && state.selectedDocument.pages) {
|
|
79
|
+
return state.selectedDocument.pages[index];
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
},
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Checks if is to scroll to an annotation in the document
|
|
86
|
+
*/
|
|
87
|
+
scrollDocumentToAnnotation: (state) => {
|
|
88
|
+
return (
|
|
89
|
+
state.documentAnnotationSelected &&
|
|
90
|
+
state.documentAnnotationSelected.scrollTo
|
|
91
|
+
);
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Checks if the document is categorized and ready to start the review
|
|
96
|
+
*/
|
|
97
|
+
categorizationIsConfirmed: (state) => {
|
|
98
|
+
if (state.selectedDocument) {
|
|
99
|
+
if (
|
|
100
|
+
state.selectedDocument.category_is_revised ||
|
|
101
|
+
state.selectedDocument.is_reviewed
|
|
102
|
+
) {
|
|
103
|
+
return true;
|
|
104
|
+
} else if (!state.selectedDocument.category) {
|
|
105
|
+
return false;
|
|
106
|
+
} else {
|
|
107
|
+
// check if there's any annotation already approved
|
|
108
|
+
const found = state.annotations.find((annotation) => {
|
|
109
|
+
return annotation.revised;
|
|
110
|
+
});
|
|
111
|
+
return found != undefined;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return false;
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Gets labels for an annotation creation from a label/annotation set
|
|
119
|
+
*/
|
|
120
|
+
labelsFilteredForAnnotationCreation: (_, getters) => (set) => {
|
|
121
|
+
let availableLabels = [];
|
|
122
|
+
if (set.id && set.labels) {
|
|
123
|
+
// check if label can be multiple, if there's already an annotation created & if it's a negative annotation
|
|
124
|
+
set.labels.map((label) => {
|
|
125
|
+
// check if we already added the same label to the array
|
|
126
|
+
const found = availableLabels.find((l) => l.id === label.id);
|
|
127
|
+
|
|
128
|
+
if (found) return;
|
|
129
|
+
|
|
130
|
+
if (label.annotations.length === 0) {
|
|
131
|
+
availableLabels.push(label);
|
|
132
|
+
} else {
|
|
133
|
+
if (label.has_multiple_top_candidates) {
|
|
134
|
+
availableLabels.push(label);
|
|
135
|
+
} else {
|
|
136
|
+
// if the label has negative annotations, we show the label
|
|
137
|
+
label.annotations.map((annotation) => {
|
|
138
|
+
if (getters.isNegative(annotation)) {
|
|
139
|
+
availableLabels.push(label);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
} else if (set.labels) {
|
|
146
|
+
// if not existing ann set, then return all labels
|
|
147
|
+
availableLabels = set.labels;
|
|
148
|
+
}
|
|
149
|
+
return availableLabels;
|
|
150
|
+
},
|
|
151
|
+
|
|
152
|
+
/* Checks if annotation is in deleted state */
|
|
153
|
+
isAnnotationDeleted: (state) => (annotation) => {
|
|
154
|
+
if (annotation) {
|
|
155
|
+
return annotation.revised && !annotation.is_correct;
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
/* Checks if the label has annotations to show */
|
|
161
|
+
labelHasAnnotations: (_, getters) => (label) => {
|
|
162
|
+
const annotations = label.annotations.filter((annotation) => {
|
|
163
|
+
return !getters.isAnnotationDeleted(annotation);
|
|
164
|
+
});
|
|
165
|
+
return annotations.length > 0;
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
/* Checks if the document has an annotation set */
|
|
169
|
+
annotationSetExists: (state) => (annotationSetId) => {
|
|
170
|
+
return state.annotationSets.find((annSet) => annSet.id === annotationSetId);
|
|
171
|
+
},
|
|
172
|
+
|
|
173
|
+
/* Get annotation sets created in table */
|
|
174
|
+
annotationSetsInTable: (state) => () => {
|
|
175
|
+
const annotationSetsList = {};
|
|
176
|
+
if (MULTI_ANN_TABLE_FEATURE) {
|
|
177
|
+
state.annotationSets.forEach((annotationSet) => {
|
|
178
|
+
let addAnnotationSet = false;
|
|
179
|
+
if (annotationSet.labels) {
|
|
180
|
+
annotationSet.labels.forEach((label) => {
|
|
181
|
+
if (
|
|
182
|
+
label.annotations &&
|
|
183
|
+
label.annotations.find(
|
|
184
|
+
(annotation) =>
|
|
185
|
+
annotation.origin && annotation.origin === table_reference_api
|
|
186
|
+
)
|
|
187
|
+
) {
|
|
188
|
+
addAnnotationSet = true;
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
if (addAnnotationSet) {
|
|
194
|
+
// group by label set
|
|
195
|
+
if (annotationSetsList[`${annotationSet.label_set.id}`]) {
|
|
196
|
+
annotationSetsList[`${annotationSet.label_set.id}`].push(
|
|
197
|
+
annotationSet
|
|
198
|
+
);
|
|
199
|
+
} else {
|
|
200
|
+
annotationSetsList[`${annotationSet.label_set.id}`] = [
|
|
201
|
+
annotationSet,
|
|
202
|
+
];
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
return annotationSetsList;
|
|
208
|
+
},
|
|
209
|
+
|
|
210
|
+
/* Get annotation sets without tables */
|
|
211
|
+
annotationSetsToShowInList: (state) => () => {
|
|
212
|
+
const annotationSetsList = [];
|
|
213
|
+
state.annotationSets.forEach((annotationSet) => {
|
|
214
|
+
let addAnnotationSet = true;
|
|
215
|
+
if (annotationSet.labels) {
|
|
216
|
+
annotationSet.labels.forEach((label) => {
|
|
217
|
+
if (
|
|
218
|
+
MULTI_ANN_TABLE_FEATURE &&
|
|
219
|
+
label.annotations &&
|
|
220
|
+
label.annotations.find(
|
|
221
|
+
(annotation) =>
|
|
222
|
+
annotation.origin && annotation.origin === table_reference_api
|
|
223
|
+
)
|
|
224
|
+
) {
|
|
225
|
+
addAnnotationSet = false;
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
if (addAnnotationSet) {
|
|
231
|
+
annotationSetsList.push(annotationSet);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
return annotationSetsList;
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
/* Get annotations inside a list of annotation sets */
|
|
238
|
+
annotationsInAnnotationsSets: (state) => (annotationsSets) => {
|
|
239
|
+
const annotations = [];
|
|
240
|
+
annotationsSets.forEach((annotationSet) => {
|
|
241
|
+
annotationSet.labels.forEach((label) => {
|
|
242
|
+
label.annotations.forEach((annotation) => {
|
|
243
|
+
annotations.push(annotation);
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
return annotations;
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
/* Process annotations and extract labels and sets */
|
|
251
|
+
processAnnotationSets: (state, getters) => (annotationSets) => {
|
|
252
|
+
// group annotations for sidebar
|
|
253
|
+
const annotations = [];
|
|
254
|
+
const labels = [];
|
|
255
|
+
const processedAnnotationSets = annotationSets.map((annotationSet) => {
|
|
256
|
+
const annotationSetLabels = annotationSet.labels.map((label) => {
|
|
257
|
+
// add annotations to the document array
|
|
258
|
+
annotations.push(...label.annotations);
|
|
259
|
+
labels.push(label);
|
|
260
|
+
// add labels to the labels array
|
|
261
|
+
return label;
|
|
262
|
+
});
|
|
263
|
+
annotationSet.labels = annotationSetLabels;
|
|
264
|
+
return annotationSet;
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
return {
|
|
268
|
+
annotationSets: processedAnnotationSets,
|
|
269
|
+
labels,
|
|
270
|
+
annotations,
|
|
271
|
+
};
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
/* Checks if there are annotations correct in the document */
|
|
275
|
+
documentHasCorrectAnnotations: (state) => {
|
|
276
|
+
if (
|
|
277
|
+
!state.annotations ||
|
|
278
|
+
(state.annotations &&
|
|
279
|
+
state.annotations.filter((ann) => ann.is_correct).length > 0)
|
|
280
|
+
) {
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
return false;
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
/* Returns the number of accepted annotations in a label */
|
|
287
|
+
numberOfAcceptedAnnotationsInLabel: (_) => (label) => {
|
|
288
|
+
const annotations = label.annotations.filter((annotation) => {
|
|
289
|
+
return annotation.revised && annotation.is_correct;
|
|
290
|
+
});
|
|
291
|
+
return annotations.length;
|
|
292
|
+
},
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Checks if theres a group of annotation sets and add an index number to them
|
|
296
|
+
*/
|
|
297
|
+
numberOfAnnotationSetGroup: (state) => (annotationSet) => {
|
|
298
|
+
let found = false;
|
|
299
|
+
let value = 0;
|
|
300
|
+
let index = 0;
|
|
301
|
+
if (state.annotationSets) {
|
|
302
|
+
state.annotationSets.map((annotationSetTemp) => {
|
|
303
|
+
if (
|
|
304
|
+
annotationSetTemp.id !== annotationSet.id &&
|
|
305
|
+
annotationSetTemp.label_set.id === annotationSet.label_set.id &&
|
|
306
|
+
annotationSetTemp.label_set.name === annotationSet.label_set.name
|
|
307
|
+
) {
|
|
308
|
+
found = true;
|
|
309
|
+
index++;
|
|
310
|
+
} else if (
|
|
311
|
+
annotationSetTemp.label_set.id === annotationSet.label_set.id
|
|
312
|
+
) {
|
|
313
|
+
value = index;
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
return found ? `${value + 1}` : "";
|
|
317
|
+
}
|
|
318
|
+
return "";
|
|
319
|
+
},
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Get label with annotations filtered if the label supports multiple or not
|
|
323
|
+
*/
|
|
324
|
+
annotationsInLabelFiltered: (state) => (label) => {
|
|
325
|
+
let labelToReturn;
|
|
326
|
+
if (
|
|
327
|
+
label.has_multiple_top_candidates === false &&
|
|
328
|
+
label.annotations &&
|
|
329
|
+
label.annotations.length > 1
|
|
330
|
+
) {
|
|
331
|
+
let highestConfidenceAnnotation = label.annotations[0];
|
|
332
|
+
for (let i = 1; i < label.annotations.length; i++) {
|
|
333
|
+
// check which one has more confidence or if it's the same, then check if one is revised or not
|
|
334
|
+
if (
|
|
335
|
+
highestConfidenceAnnotation.confidence <
|
|
336
|
+
label.annotations[i].confidence ||
|
|
337
|
+
(highestConfidenceAnnotation.confidence ===
|
|
338
|
+
label.annotations[i].confidence &&
|
|
339
|
+
label.annotations[i].revised)
|
|
340
|
+
) {
|
|
341
|
+
highestConfidenceAnnotation = label.annotations[i];
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
labelToReturn = {
|
|
345
|
+
...label,
|
|
346
|
+
annotations: [highestConfidenceAnnotation],
|
|
347
|
+
};
|
|
348
|
+
} else {
|
|
349
|
+
labelToReturn = {
|
|
350
|
+
...label,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
return labelToReturn;
|
|
354
|
+
},
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* Checks if annotation is being edited
|
|
358
|
+
*/
|
|
359
|
+
isAnnotationInEditMode:
|
|
360
|
+
(state) =>
|
|
361
|
+
(annotationId, index = null) => {
|
|
362
|
+
if (state.editAnnotation && annotationId) {
|
|
363
|
+
if (index != null) {
|
|
364
|
+
return (
|
|
365
|
+
state.editAnnotation.id === annotationId &&
|
|
366
|
+
state.editAnnotation.index === index
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
return state.editAnnotation.id === annotationId;
|
|
370
|
+
}
|
|
371
|
+
},
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Get number of empty labels per annotation set
|
|
375
|
+
*/
|
|
376
|
+
emptyLabels: (state, getters) => (annotationSet) => {
|
|
377
|
+
const pendingEmpty = [];
|
|
378
|
+
|
|
379
|
+
annotationSet.labels.map((label) => {
|
|
380
|
+
const foundMissing = state.missingAnnotations.find(
|
|
381
|
+
(l) =>
|
|
382
|
+
l.label === label.id &&
|
|
383
|
+
annotationSet.id === l.annotation_set &&
|
|
384
|
+
annotationSet.label_set.id === l.label_set
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
const foundNegative = label.annotations.find((annotation) =>
|
|
388
|
+
getters.isNegative(annotation)
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
if (!foundMissing && (label.annotations.length === 0 || foundNegative)) {
|
|
392
|
+
pendingEmpty.push(label);
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
return pendingEmpty;
|
|
397
|
+
},
|
|
398
|
+
|
|
399
|
+
annotationIsNotFound: (state) => (annotationSet, label) => {
|
|
400
|
+
// Check if the combined label and label set have been marked as missing
|
|
401
|
+
// or if the document is in public mode
|
|
402
|
+
if (state.missingAnnotations.length === 0) {
|
|
403
|
+
return false;
|
|
404
|
+
} else {
|
|
405
|
+
const found = state.missingAnnotations.filter(
|
|
406
|
+
(el) =>
|
|
407
|
+
el.label === label.id &&
|
|
408
|
+
el.annotation_set === annotationSet.id &&
|
|
409
|
+
el.label_set === annotationSet.label_set.id
|
|
410
|
+
);
|
|
411
|
+
return found.length !== 0;
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
|
|
415
|
+
// Check if document is ready to be finished
|
|
416
|
+
isDocumentReadyToFinishReview: (state) => {
|
|
417
|
+
// check if all annotations are correct
|
|
418
|
+
let notCorrect;
|
|
419
|
+
|
|
420
|
+
const emptyAnnotations = [];
|
|
421
|
+
|
|
422
|
+
if (state.labels.length === 0) return false;
|
|
423
|
+
|
|
424
|
+
if (state.annotationSets && state.annotationSets.length > 0) {
|
|
425
|
+
state.annotationSets.forEach((annSet) => {
|
|
426
|
+
annSet.labels.map((label) => {
|
|
427
|
+
// return only labels with empty annotations
|
|
428
|
+
if (label.annotations.length === 0) {
|
|
429
|
+
emptyAnnotations.push({
|
|
430
|
+
label: label.id,
|
|
431
|
+
label_set: annSet.label_set.id,
|
|
432
|
+
});
|
|
433
|
+
}
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (state.annotations) {
|
|
439
|
+
notCorrect = state.annotations.filter((a) => !a.is_correct);
|
|
440
|
+
|
|
441
|
+
if (notCorrect) {
|
|
442
|
+
notCorrect.map((annotation) => {
|
|
443
|
+
emptyAnnotations.push(annotation);
|
|
444
|
+
});
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// if all annotations are correct
|
|
449
|
+
// and if there are no empty annotations or
|
|
450
|
+
// all empty annotations or negative annotations were marked as missing,
|
|
451
|
+
// we can finish the review
|
|
452
|
+
if (
|
|
453
|
+
!emptyAnnotations ||
|
|
454
|
+
!state.missingAnnotations ||
|
|
455
|
+
state.missingAnnotations.length === emptyAnnotations.length
|
|
456
|
+
) {
|
|
457
|
+
return true;
|
|
458
|
+
}
|
|
459
|
+
return false;
|
|
460
|
+
},
|
|
461
|
+
|
|
462
|
+
isDocumentReviewed: (state) => {
|
|
463
|
+
return state.selectedDocument.is_reviewed;
|
|
464
|
+
},
|
|
465
|
+
|
|
466
|
+
/**
|
|
467
|
+
* Get number of annotations pending review per annotation set
|
|
468
|
+
*/
|
|
469
|
+
notCorrectAnnotations: () => (annotationSet) => {
|
|
470
|
+
const labels = annotationSet.labels.filter(
|
|
471
|
+
(label) => label.annotations.length > 0
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
const annotationsWithPendingReview = [];
|
|
475
|
+
|
|
476
|
+
labels.map((label) => {
|
|
477
|
+
const foundPendingAnnotations = label.annotations.filter(
|
|
478
|
+
(ann) => !ann.is_correct && !ann.revised
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
if (foundPendingAnnotations && foundPendingAnnotations.length > 0) {
|
|
482
|
+
foundPendingAnnotations.map((annotation) => {
|
|
483
|
+
annotationsWithPendingReview.push(annotation);
|
|
484
|
+
});
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Check if we have grouped annotations by same label
|
|
488
|
+
if (state.enableGroupingFeature && label.annotations.length < 2) {
|
|
489
|
+
return annotationsWithPendingReview.length - label.annotations.length;
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
return annotationsWithPendingReview;
|
|
494
|
+
},
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Check if the document was extracted correctly and is ready to be reviewed
|
|
498
|
+
*/
|
|
499
|
+
isDocumentReadyToBeReviewed: () => (document) => {
|
|
500
|
+
return document.status_data === 2 && document.labeling_available === 1;
|
|
501
|
+
},
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Check if the document had an error during extraction
|
|
505
|
+
*/
|
|
506
|
+
documentHadErrorDuringExtraction: () => (document) => {
|
|
507
|
+
return document.status_data === 111;
|
|
508
|
+
},
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* check if the document has a dataset status of 'Training', 'Test' or 'Preparation'
|
|
512
|
+
* or if it is Ready Only / Reviewed
|
|
513
|
+
* and if so disable the option to edit the document
|
|
514
|
+
*/
|
|
515
|
+
documentCannotBeEdited:
|
|
516
|
+
(state) =>
|
|
517
|
+
(document = state.selectedDocument) => {
|
|
518
|
+
return (
|
|
519
|
+
document.dataset_status === 1 ||
|
|
520
|
+
document.dataset_status === 2 ||
|
|
521
|
+
document.dataset_status === 3 ||
|
|
522
|
+
document.is_reviewed
|
|
523
|
+
);
|
|
524
|
+
},
|
|
525
|
+
|
|
526
|
+
/**
|
|
527
|
+
* If automatic splitting is enabled for the project
|
|
528
|
+
*/
|
|
529
|
+
waitingForSplittingConfirmation: () => (document) => {
|
|
530
|
+
return document && document.status_data === 41;
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Show the Smart Split switch or not
|
|
535
|
+
*/
|
|
536
|
+
documentHasProposedSplit: () => (document) => {
|
|
537
|
+
return document.proposed_split && document.proposed_split.length > 0;
|
|
538
|
+
},
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Check the level of confidence of an annotation
|
|
542
|
+
*/
|
|
543
|
+
confidence: () => (annotation) => {
|
|
544
|
+
if (annotation) {
|
|
545
|
+
return annotation.confidence;
|
|
546
|
+
} else {
|
|
547
|
+
return null;
|
|
548
|
+
}
|
|
549
|
+
},
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Check status of annotation
|
|
553
|
+
*/
|
|
554
|
+
notExtracted: () => (annotation) => {
|
|
555
|
+
if (annotation) {
|
|
556
|
+
return !annotation.span;
|
|
557
|
+
} else {
|
|
558
|
+
return true;
|
|
559
|
+
}
|
|
560
|
+
},
|
|
561
|
+
created: () => (annotation) => {
|
|
562
|
+
if (annotation) {
|
|
563
|
+
return (
|
|
564
|
+
annotation.created_by && !annotation.revised && annotation.is_correct
|
|
565
|
+
);
|
|
566
|
+
} else {
|
|
567
|
+
return null;
|
|
568
|
+
}
|
|
569
|
+
},
|
|
570
|
+
edited: () => (annotation) => {
|
|
571
|
+
if (annotation) {
|
|
572
|
+
if (annotation.offset_string !== annotation.offset_string_original) {
|
|
573
|
+
return true;
|
|
574
|
+
} else if (annotation.created_by) {
|
|
575
|
+
return true;
|
|
576
|
+
} else {
|
|
577
|
+
return false;
|
|
578
|
+
}
|
|
579
|
+
} else {
|
|
580
|
+
return null;
|
|
581
|
+
}
|
|
582
|
+
},
|
|
583
|
+
accepted: () => (annotation) => {
|
|
584
|
+
if (annotation) {
|
|
585
|
+
return annotation.revised && annotation.is_correct;
|
|
586
|
+
} else {
|
|
587
|
+
return null;
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
isNegative: () => (annotation) => {
|
|
591
|
+
if (annotation) {
|
|
592
|
+
return !annotation.is_correct && annotation.revised;
|
|
593
|
+
} else {
|
|
594
|
+
return null;
|
|
595
|
+
}
|
|
596
|
+
},
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* Check for user who created or revised the annotation
|
|
600
|
+
*/
|
|
601
|
+
getUser: () => (annotation) => {
|
|
602
|
+
if (annotation) {
|
|
603
|
+
if (annotation.created_by && !annotation.revised) {
|
|
604
|
+
// If the annotation was created but not yet revised
|
|
605
|
+
// we show who created it
|
|
606
|
+
return annotation.created_by;
|
|
607
|
+
} else if (annotation.revised && annotation.revised_by) {
|
|
608
|
+
return annotation.revised_by;
|
|
609
|
+
} else {
|
|
610
|
+
// If both revised_by and created_by are null, we don't show any user
|
|
611
|
+
return null;
|
|
612
|
+
}
|
|
613
|
+
} else {
|
|
614
|
+
return null;
|
|
615
|
+
}
|
|
616
|
+
},
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Check if there is just one annotation set from a label set
|
|
620
|
+
*/
|
|
621
|
+
isOnlyMultipleAnnotationSet: (state) => (annotationSet) => {
|
|
622
|
+
const sameSets = state.annotationSets.filter(set => set.label_set.id === annotationSet.label_set.id);
|
|
623
|
+
|
|
624
|
+
return sameSets.length === 1 ? true : false;
|
|
625
|
+
},
|
|
626
|
+
|
|
627
|
+
/**
|
|
628
|
+
* Check if the annotation set can appear multiple times
|
|
629
|
+
*/
|
|
630
|
+
annotationSetCanBeMultiple: (_) => (annotationSet) => {
|
|
631
|
+
return annotationSet.label_set.has_multiple_annotation_sets;
|
|
632
|
+
},
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* Check if the annotation set has only empty labels
|
|
636
|
+
*/
|
|
637
|
+
annotationSetHasNoFilledLabels: (_) => (annotationSet) => {
|
|
638
|
+
const annotations = annotationSet.labels.flatMap(label => {
|
|
639
|
+
return label.annotations;
|
|
640
|
+
});
|
|
641
|
+
|
|
642
|
+
console.log(annotations);
|
|
643
|
+
|
|
644
|
+
return annotations.length === 0 ? true : false;
|
|
645
|
+
},
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
const actions = {
|
|
649
|
+
startLoading: ({ commit }) => {
|
|
650
|
+
commit("SET_LOADING", true);
|
|
651
|
+
},
|
|
652
|
+
endLoading: ({ commit }) => {
|
|
653
|
+
commit("SET_LOADING", false);
|
|
654
|
+
},
|
|
655
|
+
setDocId: ({ commit }, id) => {
|
|
656
|
+
commit("SET_PAGES", []);
|
|
657
|
+
commit("SET_DOC_ID", id);
|
|
658
|
+
},
|
|
659
|
+
setSidebarAnnotationSelected: ({ commit }, annotation) => {
|
|
660
|
+
commit("SET_ANNOTATION_SELECTED", annotation);
|
|
661
|
+
},
|
|
662
|
+
setAnnotationSets: ({ commit }, annotationSets) => {
|
|
663
|
+
commit("SET_ANNOTATION_SETS", annotationSets);
|
|
664
|
+
},
|
|
665
|
+
setEditAnnotation: (
|
|
666
|
+
{ commit },
|
|
667
|
+
{ id, index, label, labelSet, annotationSet }
|
|
668
|
+
) => {
|
|
669
|
+
const value = {
|
|
670
|
+
id,
|
|
671
|
+
index,
|
|
672
|
+
label,
|
|
673
|
+
labelSet,
|
|
674
|
+
annotationSet,
|
|
675
|
+
};
|
|
676
|
+
commit("SET_EDIT_ANNOTATION", value);
|
|
677
|
+
},
|
|
678
|
+
resetEditAnnotation: ({ commit }) => {
|
|
679
|
+
commit("RESET_EDIT_ANNOTATION");
|
|
680
|
+
},
|
|
681
|
+
setAnnotations: ({ commit }, annotations) => {
|
|
682
|
+
commit("SET_ANNOTATIONS", annotations);
|
|
683
|
+
},
|
|
684
|
+
setLabels: ({ commit }, labels) => {
|
|
685
|
+
commit("SET_LABELS", labels);
|
|
686
|
+
},
|
|
687
|
+
setPages: ({ commit }, pages) => {
|
|
688
|
+
commit("SET_PAGES", pages);
|
|
689
|
+
},
|
|
690
|
+
setSelectedDocument: ({ commit }, document) => {
|
|
691
|
+
commit("SET_SELECTED_DOCUMENT", document);
|
|
692
|
+
},
|
|
693
|
+
setPublicView: ({ commit }, publicView) => {
|
|
694
|
+
commit("SET_PUBLIC_VIEW", publicView);
|
|
695
|
+
},
|
|
696
|
+
startRecalculatingAnnotations: ({ commit }) => {
|
|
697
|
+
commit("SET_RECALCULATING_ANNOTATIONS", true);
|
|
698
|
+
},
|
|
699
|
+
endRecalculatingAnnotations: ({ commit }) => {
|
|
700
|
+
commit("SET_RECALCULATING_ANNOTATIONS", false);
|
|
701
|
+
},
|
|
702
|
+
setMissingAnnotations: ({ commit }, missingAnnotations) => {
|
|
703
|
+
commit("SET_MISSING_ANNOTATIONS", missingAnnotations);
|
|
704
|
+
},
|
|
705
|
+
setErrorMessage: ({ commit, dispatch }, message) => {
|
|
706
|
+
if (message) {
|
|
707
|
+
commit("SET_SHOW_ACTION_ERROR", true);
|
|
708
|
+
} else {
|
|
709
|
+
commit("SET_SHOW_ACTION_ERROR", false);
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
commit("SET_ERROR_MESSAGE", message);
|
|
713
|
+
|
|
714
|
+
dispatch("closeErrorMessage");
|
|
715
|
+
},
|
|
716
|
+
setDocumentError: ({ commit }, value) => {
|
|
717
|
+
commit("SET_DOCUMENT_ERROR", value);
|
|
718
|
+
},
|
|
719
|
+
setAnnotationsMarkedAsMissing: ({ commit }, annotations) => {
|
|
720
|
+
commit("SET_ANNOTATIONS_MARKED_AS_MISSING", annotations);
|
|
721
|
+
},
|
|
722
|
+
setErrorMessageWidth: ({ commit }, width) => {
|
|
723
|
+
commit("SET_ERROR_MESSAGE_WIDTH", width);
|
|
724
|
+
},
|
|
725
|
+
setHoveredAnnotationSet: ({ commit }, annotationSet) => {
|
|
726
|
+
commit("SET_HOVERED_ANNOTATION_SET", annotationSet);
|
|
727
|
+
},
|
|
728
|
+
setNewAcceptedAnnotations: ({ commit }, annotations) => {
|
|
729
|
+
commit("SET_NEW_ACCEPTED_ANNOTATIONS", annotations);
|
|
730
|
+
},
|
|
731
|
+
setSplittingSuggestions: ({ commit }, value) => {
|
|
732
|
+
commit("SET_SPLITTING_SUGGESTIONS", value);
|
|
733
|
+
},
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Actions that use HTTP requests always return the axios promise,
|
|
737
|
+
* so they can be `await`ed (useful to set the `loading` status).
|
|
738
|
+
*/
|
|
739
|
+
fetchDocument: async (
|
|
740
|
+
{ commit, state, dispatch, rootState, getters },
|
|
741
|
+
pollDocumentList = false
|
|
742
|
+
) => {
|
|
743
|
+
let projectId = null;
|
|
744
|
+
let categoryId = null;
|
|
745
|
+
let isRecalculatingAnnotations = false;
|
|
746
|
+
|
|
747
|
+
const initialPage = 1;
|
|
748
|
+
|
|
749
|
+
dispatch("startLoading");
|
|
750
|
+
dispatch("display/updateCurrentPage", initialPage, {
|
|
751
|
+
root: true,
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
await HTTP.get(`documents/${state.documentId}/`)
|
|
755
|
+
.then(async (response) => {
|
|
756
|
+
if (response.data) {
|
|
757
|
+
const { labels, annotations, annotationSets } =
|
|
758
|
+
getters.processAnnotationSets(response.data.annotation_sets);
|
|
759
|
+
|
|
760
|
+
// load first page
|
|
761
|
+
if (response.data.pages.length > 0) {
|
|
762
|
+
dispatch("fetchDocumentPage", initialPage);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
// set information on the store
|
|
766
|
+
commit("SET_ANNOTATION_SETS", annotationSets);
|
|
767
|
+
commit("SET_ANNOTATIONS", annotations);
|
|
768
|
+
commit("SET_LABELS", labels);
|
|
769
|
+
commit("SET_SELECTED_DOCUMENT", response.data);
|
|
770
|
+
|
|
771
|
+
if (response.data.project) {
|
|
772
|
+
projectId = response.data.project;
|
|
773
|
+
|
|
774
|
+
dispatch("project/setProjectId", projectId, {
|
|
775
|
+
root: true,
|
|
776
|
+
});
|
|
777
|
+
dispatch("project/fetchProjectDetails", projectId, {
|
|
778
|
+
root: true,
|
|
779
|
+
});
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
if (getters.documentHasProposedSplit(response.data)) {
|
|
783
|
+
commit("SET_SPLITTING_SUGGESTIONS", response.data.proposed_split);
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
categoryId = response.data.category;
|
|
787
|
+
// TODO: add this validation to a method
|
|
788
|
+
isRecalculatingAnnotations = response.data.labeling_available !== 1;
|
|
789
|
+
}
|
|
790
|
+
})
|
|
791
|
+
.catch((error) => {
|
|
792
|
+
console.log(error, "Could not fetch document details from the backend");
|
|
793
|
+
return;
|
|
794
|
+
});
|
|
795
|
+
|
|
796
|
+
if (!state.publicView) {
|
|
797
|
+
await dispatch("fetchMissingAnnotations");
|
|
798
|
+
|
|
799
|
+
await dispatch("project/fetchCurrentUser", null, {
|
|
800
|
+
root: true,
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
// Check if we first open the document dashboard or the edit mode
|
|
804
|
+
if (
|
|
805
|
+
!state.selectedDocument.category ||
|
|
806
|
+
(!state.selectedDocument.category_is_revised &&
|
|
807
|
+
!getters.documentHasCorrectAnnotations &&
|
|
808
|
+
state.missingAnnotations.length === 0)
|
|
809
|
+
) {
|
|
810
|
+
dispatch("edit/enableEditMode", null, {
|
|
811
|
+
root: true,
|
|
812
|
+
});
|
|
813
|
+
dispatch("edit/setRenameAndCategorize", true, { root: true });
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
if (projectId) {
|
|
817
|
+
await dispatch("category/fetchCategories", projectId, {
|
|
818
|
+
root: true,
|
|
819
|
+
});
|
|
820
|
+
|
|
821
|
+
// get list of documents not reviewed
|
|
822
|
+
await dispatch("project/fetchDocumentList", "is_reviewed=false", {
|
|
823
|
+
root: true,
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
if (categoryId && rootState.category.createAvailableListOfDocuments) {
|
|
827
|
+
await dispatch(
|
|
828
|
+
"category/createAvailableDocumentsList",
|
|
829
|
+
{
|
|
830
|
+
categoryId,
|
|
831
|
+
user: rootState.project.currentUser.username,
|
|
832
|
+
poll: pollDocumentList,
|
|
833
|
+
},
|
|
834
|
+
{
|
|
835
|
+
root: true,
|
|
836
|
+
}
|
|
837
|
+
);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
if (isRecalculatingAnnotations) {
|
|
841
|
+
commit("SET_RECALCULATING_ANNOTATIONS", true);
|
|
842
|
+
dispatch("pollDocumentEndpoint");
|
|
843
|
+
}
|
|
844
|
+
dispatch("endLoading");
|
|
845
|
+
},
|
|
846
|
+
|
|
847
|
+
// Get document page data
|
|
848
|
+
fetchDocumentPage: ({ commit, state }, page) => {
|
|
849
|
+
return HTTP.get(`documents/${state.documentId}/pages/${page}/`)
|
|
850
|
+
.then((response) => {
|
|
851
|
+
commit("ADD_PAGE", response.data);
|
|
852
|
+
})
|
|
853
|
+
.catch((error) => {
|
|
854
|
+
console.log(error);
|
|
855
|
+
});
|
|
856
|
+
},
|
|
857
|
+
|
|
858
|
+
setDocumentAnnotationSelected: (
|
|
859
|
+
{ commit },
|
|
860
|
+
{ annotation, label, span, scrollTo = false }
|
|
861
|
+
) => {
|
|
862
|
+
const value = {
|
|
863
|
+
scrollTo,
|
|
864
|
+
id: annotation.id,
|
|
865
|
+
span,
|
|
866
|
+
page: span.page_index + 1,
|
|
867
|
+
labelName: label ? label.name : "",
|
|
868
|
+
};
|
|
869
|
+
commit("SET_DOCUMENT_ANNOTATION_SELECTED", value);
|
|
870
|
+
},
|
|
871
|
+
|
|
872
|
+
scrollToDocumentAnnotationSelected: ({ commit }) => {
|
|
873
|
+
commit("SET_DOCUMENT_ANNOTATION_SCROLL", true);
|
|
874
|
+
},
|
|
875
|
+
|
|
876
|
+
disableDocumentAnnotationSelected: ({ commit }) => {
|
|
877
|
+
commit("SET_DOCUMENT_ANNOTATION_SELECTED", null);
|
|
878
|
+
},
|
|
879
|
+
|
|
880
|
+
createAnnotation: (
|
|
881
|
+
{ commit, getters, dispatch },
|
|
882
|
+
{ annotation, negativeAnnotationId }
|
|
883
|
+
) => {
|
|
884
|
+
return new Promise((resolve, reject) => {
|
|
885
|
+
HTTP.post(`/annotations/`, annotation)
|
|
886
|
+
.then(async (response) => {
|
|
887
|
+
if (response.status === 201) {
|
|
888
|
+
await dispatch("fetchMissingAnnotations");
|
|
889
|
+
|
|
890
|
+
if (!getters.annotationSetExists(response.data.annotation_set)) {
|
|
891
|
+
const documentData = await dispatch("fetchDocumentData");
|
|
892
|
+
if (documentData && documentData.annotation_sets) {
|
|
893
|
+
const { labels, annotations, annotationSets } =
|
|
894
|
+
getters.processAnnotationSets(documentData.annotation_sets);
|
|
895
|
+
commit("SET_ANNOTATION_SETS", annotationSets);
|
|
896
|
+
commit("SET_ANNOTATIONS", annotations);
|
|
897
|
+
commit("SET_LABELS", labels);
|
|
898
|
+
}
|
|
899
|
+
} else {
|
|
900
|
+
commit("ADD_ANNOTATION", response.data);
|
|
901
|
+
if (negativeAnnotationId) {
|
|
902
|
+
commit("DELETE_ANNOTATION", negativeAnnotationId);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
resolve(response);
|
|
907
|
+
}
|
|
908
|
+
})
|
|
909
|
+
.catch((error) => {
|
|
910
|
+
reject(error.response);
|
|
911
|
+
console.log(error);
|
|
912
|
+
});
|
|
913
|
+
});
|
|
914
|
+
},
|
|
915
|
+
|
|
916
|
+
updateAnnotation: (
|
|
917
|
+
{ commit, getters, dispatch },
|
|
918
|
+
{ updatedValues, annotationId }
|
|
919
|
+
) => {
|
|
920
|
+
commit("SET_NEW_ACCEPTED_ANNOTATIONS", [annotationId]);
|
|
921
|
+
|
|
922
|
+
return new Promise((resolve, reject) => {
|
|
923
|
+
HTTP.patch(`/annotations/${annotationId}/`, updatedValues)
|
|
924
|
+
.then(async (response) => {
|
|
925
|
+
if (response.status === 200) {
|
|
926
|
+
commit("UPDATE_ANNOTATION", response.data);
|
|
927
|
+
commit("SET_NEW_ACCEPTED_ANNOTATIONS", null);
|
|
928
|
+
|
|
929
|
+
resolve(true);
|
|
930
|
+
}
|
|
931
|
+
})
|
|
932
|
+
.catch((error) => {
|
|
933
|
+
reject(error.response);
|
|
934
|
+
console.log(error);
|
|
935
|
+
});
|
|
936
|
+
});
|
|
937
|
+
},
|
|
938
|
+
|
|
939
|
+
deleteAnnotation: ({ commit, getters }, { annotationId, annotationSet }) => {
|
|
940
|
+
return new Promise((resolve, reject) => {
|
|
941
|
+
HTTP.delete(`/annotations/${annotationId}/`)
|
|
942
|
+
.then(async (response) => {
|
|
943
|
+
if (response.status === 204) {
|
|
944
|
+
commit("DELETE_ANNOTATION", annotationId);
|
|
945
|
+
|
|
946
|
+
// Check if the deleted annotation was the last one in a multiple annotation set
|
|
947
|
+
// and if the annotation set has no annotations
|
|
948
|
+
if (annotationSet && getters.annotationSetCanBeMultiple(annotationSet) && getters.annotationSetHasNoFilledLabels(annotationSet)) {
|
|
949
|
+
// Check if there is still 1 or more multiple annotation sets for the same label set
|
|
950
|
+
if (getters.isOnlyMultipleAnnotationSet(annotationSet)) {
|
|
951
|
+
commit("UPDATE_ANNOTATION_SET", annotationSet);
|
|
952
|
+
} else {
|
|
953
|
+
commit("DELETE_ANNOTATION_SET", annotationSet);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
resolve(true);
|
|
958
|
+
}
|
|
959
|
+
})
|
|
960
|
+
.catch((error) => {
|
|
961
|
+
reject(error.response);
|
|
962
|
+
console.log(error);
|
|
963
|
+
});
|
|
964
|
+
});
|
|
965
|
+
},
|
|
966
|
+
|
|
967
|
+
updateDocument: ({ commit, state, getters, dispatch }, updatedDocument) => {
|
|
968
|
+
return new Promise((resolve, reject) => {
|
|
969
|
+
HTTP.patch(`/documents/${state.documentId}/`, updatedDocument)
|
|
970
|
+
.then((response) => {
|
|
971
|
+
if (response.status === 200) {
|
|
972
|
+
if (updatedDocument.data_file_name) {
|
|
973
|
+
// if the only change was the file name, don't reload the page
|
|
974
|
+
// only update the file name for the selectedDocument
|
|
975
|
+
commit("UPDATE_FILE_NAME", response.data.data_file_name);
|
|
976
|
+
} else {
|
|
977
|
+
commit("SET_SELECTED_DOCUMENT", response.data);
|
|
978
|
+
|
|
979
|
+
dispatch("pollDocumentEndpoint");
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
resolve(true);
|
|
983
|
+
}
|
|
984
|
+
})
|
|
985
|
+
.catch((error) => {
|
|
986
|
+
console.log(error);
|
|
987
|
+
// check if review error
|
|
988
|
+
if (
|
|
989
|
+
error.response &&
|
|
990
|
+
error.response.request &&
|
|
991
|
+
error.response.request.response
|
|
992
|
+
) {
|
|
993
|
+
const is_reviewed = JSON.parse(error.request.response).is_reviewed;
|
|
994
|
+
if (is_reviewed && is_reviewed.length > 0) {
|
|
995
|
+
const errorData = {
|
|
996
|
+
data: [...is_reviewed],
|
|
997
|
+
};
|
|
998
|
+
reject(errorData);
|
|
999
|
+
return;
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
reject(error.response);
|
|
1003
|
+
});
|
|
1004
|
+
});
|
|
1005
|
+
},
|
|
1006
|
+
|
|
1007
|
+
fetchMissingAnnotations: ({ commit, state, getters }) => {
|
|
1008
|
+
return new Promise((resolve, reject) => {
|
|
1009
|
+
return HTTP.get(
|
|
1010
|
+
`/missing-annotations/?document=${state.documentId}&limit=100`
|
|
1011
|
+
)
|
|
1012
|
+
.then((response) => {
|
|
1013
|
+
commit("SET_MISSING_ANNOTATIONS", response.data.results);
|
|
1014
|
+
resolve(true);
|
|
1015
|
+
})
|
|
1016
|
+
.catch((error) => {
|
|
1017
|
+
reject(error.response);
|
|
1018
|
+
console.log(error);
|
|
1019
|
+
});
|
|
1020
|
+
});
|
|
1021
|
+
},
|
|
1022
|
+
|
|
1023
|
+
addMissingAnnotations: ({ commit, getters }, missingAnnotations) => {
|
|
1024
|
+
return new Promise((resolve, reject) => {
|
|
1025
|
+
HTTP.post(`/missing-annotations/`, missingAnnotations)
|
|
1026
|
+
.then(async (response) => {
|
|
1027
|
+
if (response.status === 201) {
|
|
1028
|
+
commit("SET_ANNOTATIONS_MARKED_AS_MISSING", null);
|
|
1029
|
+
commit("ADD_MISSING_ANNOTATIONS", response.data);
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
resolve(response);
|
|
1033
|
+
})
|
|
1034
|
+
.catch((error) => {
|
|
1035
|
+
reject(error.response);
|
|
1036
|
+
console.log(error);
|
|
1037
|
+
});
|
|
1038
|
+
});
|
|
1039
|
+
},
|
|
1040
|
+
|
|
1041
|
+
deleteMissingAnnotation: ({ commit, getters }, id) => {
|
|
1042
|
+
return new Promise((resolve, reject) => {
|
|
1043
|
+
return HTTP.delete(`/missing-annotations/${id}/`)
|
|
1044
|
+
.then((response) => {
|
|
1045
|
+
if (response.status === 204) {
|
|
1046
|
+
commit("DELETE_MISSING_ANNOTATION", id);
|
|
1047
|
+
resolve(true);
|
|
1048
|
+
}
|
|
1049
|
+
})
|
|
1050
|
+
.catch((error) => {
|
|
1051
|
+
reject(error.response);
|
|
1052
|
+
console.log(error);
|
|
1053
|
+
});
|
|
1054
|
+
});
|
|
1055
|
+
},
|
|
1056
|
+
|
|
1057
|
+
updateMultipleAnnotations: ({ state, commit }, annotations) => {
|
|
1058
|
+
commit("SET_NEW_ACCEPTED_ANNOTATIONS", annotations.ids);
|
|
1059
|
+
|
|
1060
|
+
return new Promise((resolve, reject) => {
|
|
1061
|
+
return HTTP.patch(
|
|
1062
|
+
`documents/${state.documentId}/update-annotations/`,
|
|
1063
|
+
annotations
|
|
1064
|
+
)
|
|
1065
|
+
.then((response) => {
|
|
1066
|
+
if (response.status === 200) {
|
|
1067
|
+
response.data.map((annotation) => {
|
|
1068
|
+
commit("UPDATE_ANNOTATION", annotation);
|
|
1069
|
+
});
|
|
1070
|
+
commit("SET_NEW_ACCEPTED_ANNOTATIONS", null);
|
|
1071
|
+
resolve(true);
|
|
1072
|
+
}
|
|
1073
|
+
})
|
|
1074
|
+
.catch((error) => {
|
|
1075
|
+
console.log(error);
|
|
1076
|
+
reject(error.response);
|
|
1077
|
+
});
|
|
1078
|
+
});
|
|
1079
|
+
},
|
|
1080
|
+
|
|
1081
|
+
fetchDocumentStatus: ({ state, getters }) => {
|
|
1082
|
+
return new Promise((resolve, reject) => {
|
|
1083
|
+
return HTTP.get(
|
|
1084
|
+
`documents/${state.documentId}/?fields=status_data,labeling_available`
|
|
1085
|
+
)
|
|
1086
|
+
.then((response) => {
|
|
1087
|
+
if (
|
|
1088
|
+
getters.isDocumentReadyToBeReviewed(response.data) ||
|
|
1089
|
+
getters.waitingForSplittingConfirmation(response.data)
|
|
1090
|
+
) {
|
|
1091
|
+
// ready or has splitting suggestions
|
|
1092
|
+
return resolve(true);
|
|
1093
|
+
} else if (getters.documentHadErrorDuringExtraction(response.data)) {
|
|
1094
|
+
// error
|
|
1095
|
+
return reject();
|
|
1096
|
+
} else {
|
|
1097
|
+
// not yet ready
|
|
1098
|
+
return resolve(false);
|
|
1099
|
+
}
|
|
1100
|
+
})
|
|
1101
|
+
.catch((error) => {
|
|
1102
|
+
reject(error.response);
|
|
1103
|
+
console.log(error);
|
|
1104
|
+
});
|
|
1105
|
+
});
|
|
1106
|
+
},
|
|
1107
|
+
|
|
1108
|
+
// Get document data
|
|
1109
|
+
fetchDocumentData: ({ state }) => {
|
|
1110
|
+
return new Promise((resolve, reject) => {
|
|
1111
|
+
HTTP.get(`documents/${state.documentId}/`)
|
|
1112
|
+
.then((response) => {
|
|
1113
|
+
return resolve(response.data);
|
|
1114
|
+
})
|
|
1115
|
+
.catch((error) => {
|
|
1116
|
+
reject(error);
|
|
1117
|
+
console.log(error);
|
|
1118
|
+
});
|
|
1119
|
+
});
|
|
1120
|
+
},
|
|
1121
|
+
|
|
1122
|
+
// Poll Document endpoint to know if the Document is ready to be reviewed
|
|
1123
|
+
// or even if there was an error during the extraction
|
|
1124
|
+
pollDocumentEndpoint: ({ dispatch }) => {
|
|
1125
|
+
return dispatch("fetchDocumentStatus")
|
|
1126
|
+
.then((ready) => {
|
|
1127
|
+
if (ready) {
|
|
1128
|
+
// Stop document recalculating annotations
|
|
1129
|
+
dispatch("endRecalculatingAnnotations");
|
|
1130
|
+
dispatch("fetchDocument");
|
|
1131
|
+
} else {
|
|
1132
|
+
sleep(documentPollDuration);
|
|
1133
|
+
dispatch("pollDocumentEndpoint");
|
|
1134
|
+
}
|
|
1135
|
+
})
|
|
1136
|
+
.catch((error) => {
|
|
1137
|
+
dispatch("setDocumentError", true);
|
|
1138
|
+
console.log(error);
|
|
1139
|
+
});
|
|
1140
|
+
},
|
|
1141
|
+
|
|
1142
|
+
createErrorMessage: (
|
|
1143
|
+
{ commit, dispatch },
|
|
1144
|
+
{ error, serverErrorMessage, defaultErrorMessage }
|
|
1145
|
+
) => {
|
|
1146
|
+
// check type of error
|
|
1147
|
+
if (error && error.status >= 500 && error.status < 600) {
|
|
1148
|
+
dispatch("setErrorMessage", serverErrorMessage);
|
|
1149
|
+
commit("SET_SERVER_ERROR", true);
|
|
1150
|
+
} else if (error.data && error.data.length > 0) {
|
|
1151
|
+
dispatch("setErrorMessage", error.data[0]);
|
|
1152
|
+
} else {
|
|
1153
|
+
dispatch("setErrorMessage", defaultErrorMessage);
|
|
1154
|
+
}
|
|
1155
|
+
},
|
|
1156
|
+
|
|
1157
|
+
closeErrorMessage: ({ commit }) => {
|
|
1158
|
+
setTimeout(() => {
|
|
1159
|
+
commit("SET_ERROR_MESSAGE", null);
|
|
1160
|
+
commit("SET_SHOW_ACTION_ERROR", false);
|
|
1161
|
+
commit("SET_SERVER_ERROR", false);
|
|
1162
|
+
}, 5000);
|
|
1163
|
+
},
|
|
1164
|
+
|
|
1165
|
+
contactSupport: ({ rootState }, error) => {
|
|
1166
|
+
const url = "https://konfuzio.com/support/";
|
|
1167
|
+
const params = `project=${rootState.project.projectId}&email=${rootState.project.currentUser.username}&issue=${error}`;
|
|
1168
|
+
const fullUrl = `${url}?${params}`;
|
|
1169
|
+
|
|
1170
|
+
window.open(fullUrl, "_blank");
|
|
1171
|
+
},
|
|
1172
|
+
|
|
1173
|
+
changeCurrentDocument: ({ commit, state, dispatch }, newDocumentId) => {
|
|
1174
|
+
// reset splitting suggestions
|
|
1175
|
+
if (state.splittingSuggestions) {
|
|
1176
|
+
commit("SET_SPLITTING_SUGGESTIONS", null);
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
if (getURLQueryParam("document") || getURLPath("d")) {
|
|
1180
|
+
navigateToNewDocumentURL(state.selectedDocument.id, newDocumentId);
|
|
1181
|
+
} else {
|
|
1182
|
+
commit("SET_DOC_ID", newDocumentId);
|
|
1183
|
+
dispatch("fetchDocument");
|
|
1184
|
+
}
|
|
1185
|
+
},
|
|
1186
|
+
};
|
|
1187
|
+
|
|
1188
|
+
const mutations = {
|
|
1189
|
+
SET_LOADING: (state, loading) => {
|
|
1190
|
+
state.loading = loading;
|
|
1191
|
+
},
|
|
1192
|
+
SET_DOC_ID: (state, id) => {
|
|
1193
|
+
if (id !== state.documentId) {
|
|
1194
|
+
state.documentId = id;
|
|
1195
|
+
}
|
|
1196
|
+
},
|
|
1197
|
+
ADD_ANNOTATION: (state, annotation) => {
|
|
1198
|
+
state.annotations.push(annotation);
|
|
1199
|
+
state.annotationSets.map((annotationSet) => {
|
|
1200
|
+
if (
|
|
1201
|
+
annotation.annotation_set === annotationSet.id &&
|
|
1202
|
+
annotation.label_set &&
|
|
1203
|
+
annotationSet.label_set.id === annotation.label_set.id
|
|
1204
|
+
) {
|
|
1205
|
+
annotationSet.labels.map((label) => {
|
|
1206
|
+
if (annotation.label && annotation.label.id === label.id) {
|
|
1207
|
+
const exists = label.annotations.find(
|
|
1208
|
+
(existingAnnotation) => existingAnnotation.id === annotation.id
|
|
1209
|
+
);
|
|
1210
|
+
|
|
1211
|
+
if (!exists) {
|
|
1212
|
+
label.annotations.push(annotation);
|
|
1213
|
+
return;
|
|
1214
|
+
}
|
|
1215
|
+
}
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
});
|
|
1219
|
+
},
|
|
1220
|
+
UPDATE_ANNOTATION: (state, annotation) => {
|
|
1221
|
+
const indexOfAnnotationInAnnotations = state.annotations.findIndex(
|
|
1222
|
+
(existingAnnotation) => existingAnnotation.id === annotation.id
|
|
1223
|
+
);
|
|
1224
|
+
if (indexOfAnnotationInAnnotations > -1) {
|
|
1225
|
+
state.annotations.splice(indexOfAnnotationInAnnotations, 1, annotation);
|
|
1226
|
+
}
|
|
1227
|
+
let updatedAnnotation = false;
|
|
1228
|
+
state.annotationSets.forEach((annotationSet) => {
|
|
1229
|
+
if (updatedAnnotation) {
|
|
1230
|
+
return;
|
|
1231
|
+
}
|
|
1232
|
+
annotationSet.labels.forEach((label) => {
|
|
1233
|
+
const indexOfAnnotationAnnotationSets = label.annotations.findIndex(
|
|
1234
|
+
(existingAnnotation) => existingAnnotation.id === annotation.id
|
|
1235
|
+
);
|
|
1236
|
+
if (indexOfAnnotationAnnotationSets > -1) {
|
|
1237
|
+
// checks if an annotation label was changed and add it to the new label
|
|
1238
|
+
if (annotation.label && annotation.label.id !== label.id) {
|
|
1239
|
+
label.annotations.splice(indexOfAnnotationAnnotationSets, 1);
|
|
1240
|
+
|
|
1241
|
+
const labelToAdd = annotationSet.labels.find(
|
|
1242
|
+
(labelToAdd) => labelToAdd.id === annotation.label.id
|
|
1243
|
+
);
|
|
1244
|
+
labelToAdd.annotations.push(annotation);
|
|
1245
|
+
} else {
|
|
1246
|
+
label.annotations.splice(
|
|
1247
|
+
indexOfAnnotationAnnotationSets,
|
|
1248
|
+
1,
|
|
1249
|
+
annotation
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
updatedAnnotation = true;
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
});
|
|
1256
|
+
});
|
|
1257
|
+
},
|
|
1258
|
+
DELETE_ANNOTATION: (state, annotationId) => {
|
|
1259
|
+
const indexOfAnnotationToDelete = state.annotations.findIndex(
|
|
1260
|
+
(existingAnnotation) => existingAnnotation.id === annotationId
|
|
1261
|
+
);
|
|
1262
|
+
if (indexOfAnnotationToDelete > -1) {
|
|
1263
|
+
state.annotations.splice(indexOfAnnotationToDelete, 1);
|
|
1264
|
+
}
|
|
1265
|
+
let deleted = false;
|
|
1266
|
+
state.annotationSets.forEach((annotationSet) => {
|
|
1267
|
+
if (deleted) {
|
|
1268
|
+
return;
|
|
1269
|
+
}
|
|
1270
|
+
annotationSet.labels.forEach((label) => {
|
|
1271
|
+
const indexOfAnnotationInLabelToDelete = label.annotations.findIndex(
|
|
1272
|
+
(existingAnnotation) => existingAnnotation.id === annotationId
|
|
1273
|
+
);
|
|
1274
|
+
if (indexOfAnnotationInLabelToDelete > -1) {
|
|
1275
|
+
label.annotations.splice(indexOfAnnotationInLabelToDelete, 1);
|
|
1276
|
+
deleted = true;
|
|
1277
|
+
return;
|
|
1278
|
+
}
|
|
1279
|
+
});
|
|
1280
|
+
});
|
|
1281
|
+
},
|
|
1282
|
+
SET_ANNOTATIONS: (state, annotations) => {
|
|
1283
|
+
state.annotations = annotations;
|
|
1284
|
+
},
|
|
1285
|
+
SET_ANNOTATION_SETS: (state, annotationSets) => {
|
|
1286
|
+
state.annotationSets = annotationSets;
|
|
1287
|
+
},
|
|
1288
|
+
DELETE_ANNOTATION_SET: (state, annotationSet) => {
|
|
1289
|
+
const indexOfSetToDelete = state.annotationSets.findIndex(
|
|
1290
|
+
(existingAnnotationSet) => existingAnnotationSet.id === annotationSet.id
|
|
1291
|
+
);
|
|
1292
|
+
|
|
1293
|
+
if (indexOfSetToDelete === -1) return;
|
|
1294
|
+
|
|
1295
|
+
state.annotationSets.splice(indexOfSetToDelete, 1);
|
|
1296
|
+
},
|
|
1297
|
+
UPDATE_ANNOTATION_SET: (state, annotationSet) => {
|
|
1298
|
+
const indexOfExistingAnnotationSet = state.annotationSets.findIndex(
|
|
1299
|
+
(existingAnnotationSet) => existingAnnotationSet.id === annotationSet.id
|
|
1300
|
+
);
|
|
1301
|
+
|
|
1302
|
+
if (indexOfExistingAnnotationSet === -1) return;
|
|
1303
|
+
|
|
1304
|
+
const updatedSet = { ...annotationSet, id: null };
|
|
1305
|
+
|
|
1306
|
+
state.annotationSets.splice(indexOfExistingAnnotationSet, 1, updatedSet);
|
|
1307
|
+
},
|
|
1308
|
+
SET_LABELS: (state, labels) => {
|
|
1309
|
+
state.labels = labels;
|
|
1310
|
+
},
|
|
1311
|
+
SET_ANNOTATION_SELECTED: (state, annotation) => {
|
|
1312
|
+
state.sidebarAnnotationSelected = annotation;
|
|
1313
|
+
},
|
|
1314
|
+
SET_EDIT_ANNOTATION: (state, editAnnotation) => {
|
|
1315
|
+
state.editAnnotation = editAnnotation;
|
|
1316
|
+
},
|
|
1317
|
+
RESET_EDIT_ANNOTATION: (state) => {
|
|
1318
|
+
state.editAnnotation = null;
|
|
1319
|
+
},
|
|
1320
|
+
ADD_PAGE: (state, page) => {
|
|
1321
|
+
// if we already have the page in the state, update it in
|
|
1322
|
+
// the pages array instead of creating a new one
|
|
1323
|
+
const existingPageIndex = state.pages.findIndex(
|
|
1324
|
+
(p) => p.number === page.number
|
|
1325
|
+
);
|
|
1326
|
+
if (existingPageIndex === -1) {
|
|
1327
|
+
state.pages.push(page);
|
|
1328
|
+
} else {
|
|
1329
|
+
state.pages[existingPageIndex] = page;
|
|
1330
|
+
}
|
|
1331
|
+
},
|
|
1332
|
+
SET_PAGES: (state, pages) => {
|
|
1333
|
+
state.pages = pages;
|
|
1334
|
+
},
|
|
1335
|
+
SET_DOCUMENT_ANNOTATION_SELECTED: (state, documentAnnotationSelected) => {
|
|
1336
|
+
state.documentAnnotationSelected = documentAnnotationSelected;
|
|
1337
|
+
},
|
|
1338
|
+
SET_DOCUMENT_ANNOTATION_SCROLL: (state, scrollTo) => {
|
|
1339
|
+
if (state.documentAnnotationSelected) {
|
|
1340
|
+
state.documentAnnotationSelected.scrollTo = scrollTo;
|
|
1341
|
+
}
|
|
1342
|
+
},
|
|
1343
|
+
SET_SELECTED_DOCUMENT: (state, document) => {
|
|
1344
|
+
state.selectedDocument = document;
|
|
1345
|
+
|
|
1346
|
+
// this is to handle cache when a document is edited or changed
|
|
1347
|
+
if (state.selectedDocument) {
|
|
1348
|
+
state.selectedDocument.downloaded_at = Date.now();
|
|
1349
|
+
}
|
|
1350
|
+
},
|
|
1351
|
+
SET_RECALCULATING_ANNOTATIONS: (state, recalculatingAnnotations) => {
|
|
1352
|
+
state.recalculatingAnnotations = recalculatingAnnotations;
|
|
1353
|
+
},
|
|
1354
|
+
SET_MISSING_ANNOTATIONS: (state, missingAnnotations) => {
|
|
1355
|
+
state.missingAnnotations = missingAnnotations;
|
|
1356
|
+
},
|
|
1357
|
+
ADD_MISSING_ANNOTATIONS: (state, annotations) => {
|
|
1358
|
+
if (annotations && annotations.length > 0) {
|
|
1359
|
+
annotations.map((annotation) => {
|
|
1360
|
+
// check if already in missingAnnotations
|
|
1361
|
+
const found = state.missingAnnotations.find(
|
|
1362
|
+
(missingAnnotation) => missingAnnotation.id === annotation.id
|
|
1363
|
+
);
|
|
1364
|
+
|
|
1365
|
+
if (found) {
|
|
1366
|
+
const indexOfAnnotation = state.missingAnnotations.findIndex(
|
|
1367
|
+
(missingAnnotation) => missingAnnotation.id === annotation.id
|
|
1368
|
+
);
|
|
1369
|
+
|
|
1370
|
+
if (indexOfAnnotation > -1) {
|
|
1371
|
+
state.missingAnnotations.splice(indexOfAnnotation, 1, annotation);
|
|
1372
|
+
}
|
|
1373
|
+
} else {
|
|
1374
|
+
state.missingAnnotations.push(annotation);
|
|
1375
|
+
}
|
|
1376
|
+
});
|
|
1377
|
+
} else {
|
|
1378
|
+
state.missingAnnotations.push(annotations);
|
|
1379
|
+
}
|
|
1380
|
+
},
|
|
1381
|
+
DELETE_MISSING_ANNOTATION: (state, id) => {
|
|
1382
|
+
const indexOfAnnotationToDelete = state.missingAnnotations.findIndex(
|
|
1383
|
+
(annotation) => annotation.id === id
|
|
1384
|
+
);
|
|
1385
|
+
|
|
1386
|
+
if (indexOfAnnotationToDelete > -1) {
|
|
1387
|
+
state.missingAnnotations.splice(indexOfAnnotationToDelete, 1);
|
|
1388
|
+
}
|
|
1389
|
+
},
|
|
1390
|
+
SET_SHOW_ACTION_ERROR: (state, value) => {
|
|
1391
|
+
state.showActionError = value;
|
|
1392
|
+
},
|
|
1393
|
+
SET_ERROR_MESSAGE: (state, message) => {
|
|
1394
|
+
state.errorMessage = message;
|
|
1395
|
+
},
|
|
1396
|
+
SET_DOCUMENT_ERROR: (state, value) => {
|
|
1397
|
+
state.showDocumentError = value;
|
|
1398
|
+
},
|
|
1399
|
+
SET_ANNOTATIONS_MARKED_AS_MISSING: (state, annotations) => {
|
|
1400
|
+
state.annotationsMarkedAsMissing = annotations;
|
|
1401
|
+
},
|
|
1402
|
+
SET_ERROR_MESSAGE_WIDTH: (state, width) => {
|
|
1403
|
+
state.errorMessageWidth = width;
|
|
1404
|
+
},
|
|
1405
|
+
SET_PUBLIC_VIEW: (state, value) => {
|
|
1406
|
+
state.publicView = value;
|
|
1407
|
+
},
|
|
1408
|
+
SET_DOCUMENT_IS_READY: (state, value) => {
|
|
1409
|
+
state.documentIsReady = value;
|
|
1410
|
+
},
|
|
1411
|
+
SET_DOCUMENT_HAS_ERROR: (state, value) => {
|
|
1412
|
+
state.documentHasError = value;
|
|
1413
|
+
},
|
|
1414
|
+
SET_HOVERED_ANNOTATION_SET: (state, hoveredAnnotationSet) => {
|
|
1415
|
+
state.hoveredAnnotationSet = hoveredAnnotationSet;
|
|
1416
|
+
},
|
|
1417
|
+
SET_NEW_ACCEPTED_ANNOTATIONS: (state, annotations) => {
|
|
1418
|
+
state.newAcceptedAnnotations = annotations;
|
|
1419
|
+
},
|
|
1420
|
+
SET_SERVER_ERROR: (state, value) => {
|
|
1421
|
+
state.serverError = value;
|
|
1422
|
+
},
|
|
1423
|
+
|
|
1424
|
+
UPDATE_FILE_NAME: (state, value) => {
|
|
1425
|
+
state.selectedDocument.data_file_name = value;
|
|
1426
|
+
},
|
|
1427
|
+
SET_SPLITTING_SUGGESTIONS: (state, array) => {
|
|
1428
|
+
state.splittingSuggestions = array;
|
|
1429
|
+
},
|
|
1430
|
+
};
|
|
1431
|
+
|
|
1432
|
+
export default {
|
|
1433
|
+
namespaced: true,
|
|
1434
|
+
state,
|
|
1435
|
+
getters,
|
|
1436
|
+
actions,
|
|
1437
|
+
mutations,
|
|
1438
|
+
};
|