@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.
Files changed (143) hide show
  1. package/.eslintrc.js +10 -10
  2. package/.prettierrc.json +1 -1
  3. package/LICENSE +21 -21
  4. package/README.md +24 -24
  5. package/cypress.config.js +13 -13
  6. package/dist/js/app.js +1 -1
  7. package/dist/js/app.js.map +1 -1
  8. package/dist/js/chunk-vendors.js +1 -1
  9. package/dist/js/chunk-vendors.js.map +1 -1
  10. package/jest.config.js +4 -4
  11. package/package.json +66 -66
  12. package/src/api.js +82 -82
  13. package/src/assets/images/AcceptedCheckMark.vue +8 -8
  14. package/src/assets/images/AcceptedUser.vue +8 -8
  15. package/src/assets/images/ActionIcon.vue +60 -60
  16. package/src/assets/images/ArrowDownKey.vue +11 -11
  17. package/src/assets/images/ArrowUpKey.vue +11 -11
  18. package/src/assets/images/CategoryIconImg.vue +13 -13
  19. package/src/assets/images/CheckMark.vue +8 -8
  20. package/src/assets/images/DraggableIcon.vue +14 -14
  21. package/src/assets/images/EditDocIcon.vue +12 -12
  22. package/src/assets/images/EmptyStateImg.vue +129 -129
  23. package/src/assets/images/ErrorIcon.vue +28 -28
  24. package/src/assets/images/EyeIcon.vue +11 -11
  25. package/src/assets/images/FileNameNotSavedImage.vue +26 -26
  26. package/src/assets/images/FileNameSavedImage.vue +14 -14
  27. package/src/assets/images/FitZoomIcon.vue +16 -16
  28. package/src/assets/images/GridIcon.vue +16 -16
  29. package/src/assets/images/KeyboardIcon.vue +16 -16
  30. package/src/assets/images/MagicWandIcon.vue +16 -16
  31. package/src/assets/images/MinusIcon.vue +13 -13
  32. package/src/assets/images/NotFoundIcon.vue +16 -16
  33. package/src/assets/images/NotOptimizedIllustration.vue +651 -651
  34. package/src/assets/images/PlusIcon.vue +13 -13
  35. package/src/assets/images/QuestionMark.vue +12 -12
  36. package/src/assets/images/ServerImage.vue +73 -73
  37. package/src/assets/images/SettingsIcon.vue +14 -14
  38. package/src/assets/images/SplitLines.vue +18 -18
  39. package/src/assets/images/SplitZigZag.vue +49 -49
  40. package/src/assets/images/StarIcon.vue +16 -16
  41. package/src/assets/images/StatusImg.vue +14 -14
  42. package/src/assets/images/TranslateArrows.vue +33 -33
  43. package/src/assets/scss/ann_set_table_options.scss +26 -26
  44. package/src/assets/scss/annotation_details.scss +141 -141
  45. package/src/assets/scss/choose_label_set_modal.scss +65 -65
  46. package/src/assets/scss/document_action_bar.scss +37 -37
  47. package/src/assets/scss/document_annotations.scss +558 -558
  48. package/src/assets/scss/document_category.scss +85 -85
  49. package/src/assets/scss/document_dashboard.scss +52 -52
  50. package/src/assets/scss/document_edit.scss +410 -410
  51. package/src/assets/scss/document_error.scss +81 -81
  52. package/src/assets/scss/document_name.scss +60 -60
  53. package/src/assets/scss/document_page.scss +12 -12
  54. package/src/assets/scss/document_thumbnails.scss +41 -41
  55. package/src/assets/scss/document_toolbar.scss +111 -111
  56. package/src/assets/scss/document_top_bar.scss +171 -171
  57. package/src/assets/scss/document_viewport_modal.scss +25 -25
  58. package/src/assets/scss/documents_list.scss +141 -141
  59. package/src/assets/scss/edit_page_thumbnail.scss +53 -53
  60. package/src/assets/scss/empty_state.scss +34 -34
  61. package/src/assets/scss/extracting_data.scss +35 -35
  62. package/src/assets/scss/imports.scss +1 -1
  63. package/src/assets/scss/multi_ann_table_overlay.scss +38 -38
  64. package/src/assets/scss/multi_ann_table_popup.scss +12 -12
  65. package/src/assets/scss/new_annotation.scss +102 -102
  66. package/src/assets/scss/scrolling_document.scss +19 -19
  67. package/src/assets/scss/theme.scss +801 -801
  68. package/src/assets/scss/variables.scss +66 -66
  69. package/src/components/App.cy.js +7 -7
  70. package/src/components/App.vue +187 -187
  71. package/src/components/DocumentAnnotations/AnnotationActionButtons.vue +152 -152
  72. package/src/components/DocumentAnnotations/AnnotationContent.vue +210 -210
  73. package/src/components/DocumentAnnotations/AnnotationDetails.vue +251 -251
  74. package/src/components/DocumentAnnotations/AnnotationRow.vue +752 -752
  75. package/src/components/DocumentAnnotations/AnnotationSetActionButtons.vue +89 -89
  76. package/src/components/DocumentAnnotations/ChooseLabelSetModal.vue +186 -186
  77. package/src/components/DocumentAnnotations/DocumentAnnotations.cy.js +441 -441
  78. package/src/components/DocumentAnnotations/DocumentAnnotations.vue +534 -534
  79. package/src/components/DocumentAnnotations/DocumentLabel.vue +189 -189
  80. package/src/components/DocumentAnnotations/EmptyAnnotation.vue +193 -193
  81. package/src/components/DocumentAnnotations/EmptyState.vue +21 -21
  82. package/src/components/DocumentAnnotations/ExtractingData.vue +41 -41
  83. package/src/components/DocumentAnnotations/LoadingAnnotations.vue +43 -43
  84. package/src/components/DocumentAnnotations/LoadingLabels.vue +43 -43
  85. package/src/components/DocumentAnnotations/MultiAnnotationTableOverlay.vue +338 -338
  86. package/src/components/DocumentAnnotations/index.js +8 -8
  87. package/src/components/DocumentCategory.vue +281 -281
  88. package/src/components/DocumentDashboard.vue +170 -170
  89. package/src/components/DocumentEdit/DocumentEdit.cy.js +541 -541
  90. package/src/components/DocumentEdit/DocumentEdit.vue +503 -503
  91. package/src/components/DocumentEdit/EditConfirmationModal.vue +55 -55
  92. package/src/components/DocumentEdit/EditPageThumbnail.vue +114 -114
  93. package/src/components/DocumentEdit/EditPages.vue +161 -161
  94. package/src/components/DocumentEdit/EditSidebar.vue +154 -154
  95. package/src/components/DocumentEdit/RenameAndCategorize.vue +184 -184
  96. package/src/components/DocumentEdit/SidebarButtons.vue +53 -53
  97. package/src/components/DocumentEdit/SplitInfoBar.vue +21 -21
  98. package/src/components/DocumentEdit/index.js +4 -4
  99. package/src/components/DocumentModals/DocumentErrorModal.vue +58 -58
  100. package/src/components/DocumentModals/NotOptimizedViewportModal.vue +51 -51
  101. package/src/components/DocumentPage/ActionBar.vue +48 -48
  102. package/src/components/DocumentPage/AnnSetTableOptions.vue +111 -111
  103. package/src/components/DocumentPage/BoxSelection.vue +152 -152
  104. package/src/components/DocumentPage/DocumentPage.cy.js +92 -92
  105. package/src/components/DocumentPage/DocumentPage.vue +568 -568
  106. package/src/components/DocumentPage/DocumentToolbar.cy.js +215 -215
  107. package/src/components/DocumentPage/DocumentToolbar.vue +228 -228
  108. package/src/components/DocumentPage/DummyPage.vue +55 -55
  109. package/src/components/DocumentPage/MultiAnnSelection.vue +371 -371
  110. package/src/components/DocumentPage/NewAnnotation.vue +308 -308
  111. package/src/components/DocumentPage/ScrollingDocument.vue +149 -149
  112. package/src/components/DocumentPage/ScrollingPage.vue +179 -179
  113. package/src/components/DocumentPage/index.js +5 -5
  114. package/src/components/DocumentThumbnails/DocumentThumbnails.cy.js +67 -67
  115. package/src/components/DocumentThumbnails/DocumentThumbnails.vue +132 -132
  116. package/src/components/DocumentThumbnails/LoadingThumbnail.vue +25 -25
  117. package/src/components/DocumentThumbnails/index.js +1 -1
  118. package/src/components/DocumentTopBar/DocumentName.vue +236 -236
  119. package/src/components/DocumentTopBar/DocumentTopBar.cy.js +222 -222
  120. package/src/components/DocumentTopBar/DocumentTopBar.vue +202 -202
  121. package/src/components/DocumentTopBar/DocumentTopBarButtons.vue +183 -183
  122. package/src/components/DocumentTopBar/KeyboardActionsDescription.vue +74 -74
  123. package/src/components/DocumentTopBar/index.js +3 -3
  124. package/src/components/DocumentsList/DocumentsList.vue +121 -121
  125. package/src/components/DocumentsList/index.js +1 -1
  126. package/src/components/ErrorMessage.vue +40 -40
  127. package/src/components/index.js +1 -1
  128. package/src/constants.js +5 -5
  129. package/src/directives/scroll.js +28 -28
  130. package/src/i18n.js +22 -22
  131. package/src/icons.js +45 -45
  132. package/src/locales/de.json +148 -148
  133. package/src/locales/en.json +148 -148
  134. package/src/main.js +26 -26
  135. package/src/store/category.js +191 -191
  136. package/src/store/display.js +311 -311
  137. package/src/store/document.js +1438 -1438
  138. package/src/store/edit.js +316 -316
  139. package/src/store/index.js +21 -21
  140. package/src/store/project.js +143 -143
  141. package/src/store/selection.js +210 -210
  142. package/src/utils/utils.js +54 -54
  143. package/vue.config.js +25 -25
@@ -1,338 +1,338 @@
1
- <template>
2
- <div
3
- class="multi-ann-table-overlay"
4
- :style="{
5
- left: `${left}px`,
6
- width: `${width === 0 ? '100%' : `${width}px`}`,
7
- }"
8
- >
9
- <b-table
10
- ref="table"
11
- class="multi-ann-set-table dark-header header-32"
12
- detail-icon="faScissors"
13
- :data="rows"
14
- :sticky-header="true"
15
- :narrowed="true"
16
- :bordered="false"
17
- draggable-column
18
- @columndragstart="columndragstart"
19
- @columndrop="columndrop"
20
- @columndragover="columndragover"
21
- @columndragleave="columndragleave"
22
- >
23
- <b-table-column
24
- v-for="(item, index) in isLoading ? [columns[0]] : columns"
25
- :key="index"
26
- :field="item.field"
27
- :label="item.label.name"
28
- >
29
- <template #header="{ column }">
30
- <b-dropdown
31
- :ref="getDropdownReference(item)"
32
- aria-role="list"
33
- class="header-dropdown"
34
- position="is-top-right"
35
- :close-on-click="false"
36
- scrollable
37
- @active-change="(e) => onDropdownChange(item, e)"
38
- >
39
- <template #trigger="{ active }">
40
- <DraggableIcon v-if="!isLoading" class="draggable" />
41
- <span v-if="!isLoading" :class="active ? 'active' : ''"
42
- >{{ column.label }}
43
- </span>
44
- <b-icon
45
- v-if="!isLoading"
46
- :icon="active ? 'angle-up' : 'angle-down'"
47
- size="is-small"
48
- class="arrow"
49
- />
50
- </template>
51
-
52
- <div v-if="editingLabels.length === 0">
53
- <b-dropdown-item aria-role="listitem" @click="editLabel(item)"
54
- ><span>{{ $t("edit_label") }}</span></b-dropdown-item
55
- >
56
- <b-dropdown-item
57
- aria-role="listitem"
58
- class="delete-action"
59
- @click="deleteColumn(item)"
60
- >
61
- <span>{{ $t("delete_label") }}</span></b-dropdown-item
62
- >
63
- </div>
64
- <div v-else>
65
- <b-dropdown-item
66
- v-for="label in editingLabels"
67
- :key="label.id"
68
- aria-role="listitem"
69
- :disabled="label.disabled"
70
- ><span @click="!label.disabled && changeLabel(item, label)">{{
71
- label.name
72
- }}</span></b-dropdown-item
73
- >
74
- </div>
75
- </b-dropdown>
76
- </template>
77
-
78
- <template #default="props">
79
- <div class="annotations-table">
80
- <b-skeleton v-if="isLoading" width="98%" height="90%" />
81
- <AnnotationRow
82
- v-if="!isLoading"
83
- :annotation="props.row[item.field]"
84
- :label="item.label"
85
- :annotation-set="item.annotationSet"
86
- :show-label="false"
87
- :show-buttons="false"
88
- :is-small="true"
89
- :from-table="true"
90
- />
91
- </div>
92
- </template>
93
- </b-table-column>
94
- </b-table>
95
- </div>
96
- </template>
97
-
98
- <script>
99
- import { mapState } from "vuex";
100
- import AnnotationRow from "../DocumentAnnotations/AnnotationRow";
101
- import DraggableIcon from "../../assets/images/DraggableIcon";
102
-
103
- export default {
104
- name: "MultiAnnotationTableOverlay",
105
- components: {
106
- AnnotationRow,
107
- DraggableIcon,
108
- },
109
- props: {
110
- left: {
111
- type: Number,
112
- required: false,
113
- default: 0,
114
- },
115
- width: {
116
- type: Number,
117
- required: false,
118
- default: 0,
119
- },
120
- },
121
- data() {
122
- return {
123
- rows: [],
124
- columns: [],
125
- orderedAnnotations: [],
126
- editingLabels: [],
127
- openDropdown: null,
128
- draggingColumnIndex: null,
129
- isLoading: false,
130
- };
131
- },
132
- computed: {
133
- ...mapState("display", ["showAnnSetTable"]),
134
- ...mapState("document", ["annotations"]),
135
- },
136
- watch: {
137
- showAnnSetTable() {
138
- this.handleColumns();
139
- this.handleRows();
140
- },
141
- annotations() {
142
- // if there's a change in the annotations content, we update the table
143
- this.handleColumns();
144
- this.handleRows();
145
- },
146
- columns(columns) {
147
- if (!columns || (columns && columns.length === 0)) {
148
- this.$store.dispatch("selection/disableSelection");
149
- this.$store.dispatch("document/resetEditAnnotation");
150
- this.$store.dispatch("display/showAnnSetTable", null);
151
- }
152
- },
153
- },
154
- mounted() {
155
- this.handleColumns();
156
- this.handleRows();
157
- },
158
- methods: {
159
- getDropdownReference(column) {
160
- return `editDropdown_${column.field}`;
161
- },
162
- handleColumns() {
163
- this.columns = [];
164
- const labelAlreadyExists = (label) => {
165
- return (
166
- this.columns.length > 0 &&
167
- this.columns.find((a) => a.field === `${label.id}`) != undefined
168
- );
169
- };
170
-
171
- this.showAnnSetTable.forEach((annotationSet) => {
172
- annotationSet.labels.forEach((label) => {
173
- if (!labelAlreadyExists(label) && label.annotations.length > 0) {
174
- const column = {
175
- field: `${label.id}`,
176
- label: label,
177
- annotationSet,
178
- centered: false,
179
- };
180
- this.columns.push(column);
181
- }
182
- });
183
- });
184
- },
185
-
186
- handleRows() {
187
- this.rows = [];
188
- this.orderedAnnotations = [];
189
-
190
- this.showAnnSetTable.forEach((annotationSet) => {
191
- let row = {};
192
- let toAdd = false; // to not push empty labels
193
-
194
- annotationSet.labels.forEach((label) => {
195
- if (label.annotations.length > 0) {
196
- row[label.id] = label.annotations[0];
197
- this.orderedAnnotations.push(label.annotations[0]);
198
- toAdd = true;
199
- }
200
- });
201
- if (toAdd) {
202
- this.rows.push(row);
203
- }
204
- });
205
- },
206
-
207
- async editLabel(column) {
208
- this.$store
209
- .dispatch(
210
- "project/fetchLabelSetDetails",
211
- column.annotationSet.label_set.id
212
- )
213
- .then(async (labelSet) => {
214
- this.editingLabels = [];
215
-
216
- labelSet.labels.forEach((label) => {
217
- const dropdownLabel = {
218
- ...label,
219
- disabled:
220
- this.columns.find((column) => column.label.id === label.id) !==
221
- undefined,
222
- };
223
- this.editingLabels.push(dropdownLabel);
224
- });
225
- });
226
- },
227
-
228
- async changeLabel(column, label) {
229
- this.isLoading = true;
230
- this.closeDropdown(column);
231
- for (let i = 0; i < this.rows.length; i++) {
232
- const annotationToUpdate = this.rows[i][column.label.id];
233
- await this.$store
234
- .dispatch("document/updateAnnotation", {
235
- annotationId: annotationToUpdate.id,
236
- updatedValues: { label: label.id },
237
- })
238
- .catch((error) => {
239
- this.$store.dispatch("document/createErrorMessage", {
240
- error,
241
- serverErrorMessage: this.$t("server_error"),
242
- defaultErrorMessage: this.$t("edit_error"),
243
- });
244
- });
245
- }
246
- this.isLoading = false;
247
- },
248
-
249
- async deleteColumn(column) {
250
- this.isLoading = true;
251
- this.closeDropdown(column);
252
-
253
- const annotationsToDelete = [];
254
- for (let i = 0; i < this.rows.length; i++) {
255
- const annotationToDelete = this.rows[i][column.label.id];
256
- if (annotationToDelete && annotationToDelete.id) {
257
- annotationsToDelete.push(annotationToDelete);
258
- }
259
- }
260
-
261
- annotationsToDelete.forEach(async (annotationToDelete) => {
262
- await this.$store
263
- .dispatch("document/deleteAnnotation", {
264
- annotationId: annotationToDelete.id,
265
- annotationSet: null, // TODO: test if annotation set should be added if the feature is available again
266
- })
267
- .catch((error) => {
268
- this.$store.dispatch("document/createErrorMessage", {
269
- error,
270
- serverErrorMessage: this.$t("server_error"),
271
- defaultErrorMessage: this.$t("edit_error"),
272
- });
273
- });
274
- });
275
-
276
- this.isLoading = false;
277
- },
278
-
279
- onDropdownChange(column, open) {
280
- this.editingLabels = [];
281
- this.$store.dispatch("selection/disableSelection");
282
- this.$store.dispatch("document/resetEditAnnotation");
283
- if (open) {
284
- if (
285
- this.openDropdown &&
286
- this.$refs[this.getDropdownReference(column)].length > 0
287
- ) {
288
- this.$refs[this.openDropdown][0].toggle();
289
- }
290
- this.openDropdown = this.getDropdownReference(column);
291
- } else {
292
- if (this.openDropdown === this.getDropdownReference(column)) {
293
- this.openDropdown = null;
294
- }
295
- }
296
- },
297
-
298
- closeDropdown(column) {
299
- if (
300
- this.openDropdown &&
301
- this.$refs[this.getDropdownReference(column)].length > 0
302
- ) {
303
- this.$refs[this.getDropdownReference(column)][0].toggle();
304
- this.openDropdown = null;
305
- }
306
- },
307
-
308
- columndragstart(payload) {
309
- this.draggingColumnIndex = payload.index;
310
- payload.event.dataTransfer.effectAllowed = "copy";
311
- },
312
- columndragover(payload) {
313
- payload.event.dataTransfer.dropEffect = "copy";
314
- payload.event.target.closest("th").classList.add("is-selected");
315
- payload.event.preventDefault();
316
- },
317
- columndragleave(payload) {
318
- payload.event.target.closest("th").classList.remove("is-selected");
319
- payload.event.preventDefault();
320
- },
321
- async columndrop(payload) {
322
- payload.event.target.closest("th").classList.remove("is-selected");
323
- const droppedOnColumnIndex = payload.index;
324
-
325
- const draggingColumn = this.columns[this.draggingColumnIndex];
326
- const droppedColumn = this.columns[droppedOnColumnIndex];
327
-
328
- await this.changeLabel(draggingColumn, droppedColumn.label);
329
- await this.changeLabel(droppedColumn, draggingColumn.label);
330
- },
331
- },
332
- };
333
- </script>
334
- <style
335
- scoped
336
- lang="scss"
337
- src="../../assets/scss/multi_ann_table_overlay.scss"
338
- ></style>
1
+ <template>
2
+ <div
3
+ class="multi-ann-table-overlay"
4
+ :style="{
5
+ left: `${left}px`,
6
+ width: `${width === 0 ? '100%' : `${width}px`}`,
7
+ }"
8
+ >
9
+ <b-table
10
+ ref="table"
11
+ class="multi-ann-set-table dark-header header-32"
12
+ detail-icon="faScissors"
13
+ :data="rows"
14
+ :sticky-header="true"
15
+ :narrowed="true"
16
+ :bordered="false"
17
+ draggable-column
18
+ @columndragstart="columndragstart"
19
+ @columndrop="columndrop"
20
+ @columndragover="columndragover"
21
+ @columndragleave="columndragleave"
22
+ >
23
+ <b-table-column
24
+ v-for="(item, index) in isLoading ? [columns[0]] : columns"
25
+ :key="index"
26
+ :field="item.field"
27
+ :label="item.label.name"
28
+ >
29
+ <template #header="{ column }">
30
+ <b-dropdown
31
+ :ref="getDropdownReference(item)"
32
+ aria-role="list"
33
+ class="header-dropdown"
34
+ position="is-top-right"
35
+ :close-on-click="false"
36
+ scrollable
37
+ @active-change="(e) => onDropdownChange(item, e)"
38
+ >
39
+ <template #trigger="{ active }">
40
+ <DraggableIcon v-if="!isLoading" class="draggable" />
41
+ <span v-if="!isLoading" :class="active ? 'active' : ''"
42
+ >{{ column.label }}
43
+ </span>
44
+ <b-icon
45
+ v-if="!isLoading"
46
+ :icon="active ? 'angle-up' : 'angle-down'"
47
+ size="is-small"
48
+ class="arrow"
49
+ />
50
+ </template>
51
+
52
+ <div v-if="editingLabels.length === 0">
53
+ <b-dropdown-item aria-role="listitem" @click="editLabel(item)"
54
+ ><span>{{ $t("edit_label") }}</span></b-dropdown-item
55
+ >
56
+ <b-dropdown-item
57
+ aria-role="listitem"
58
+ class="delete-action"
59
+ @click="deleteColumn(item)"
60
+ >
61
+ <span>{{ $t("delete_label") }}</span></b-dropdown-item
62
+ >
63
+ </div>
64
+ <div v-else>
65
+ <b-dropdown-item
66
+ v-for="label in editingLabels"
67
+ :key="label.id"
68
+ aria-role="listitem"
69
+ :disabled="label.disabled"
70
+ ><span @click="!label.disabled && changeLabel(item, label)">{{
71
+ label.name
72
+ }}</span></b-dropdown-item
73
+ >
74
+ </div>
75
+ </b-dropdown>
76
+ </template>
77
+
78
+ <template #default="props">
79
+ <div class="annotations-table">
80
+ <b-skeleton v-if="isLoading" width="98%" height="90%" />
81
+ <AnnotationRow
82
+ v-if="!isLoading"
83
+ :annotation="props.row[item.field]"
84
+ :label="item.label"
85
+ :annotation-set="item.annotationSet"
86
+ :show-label="false"
87
+ :show-buttons="false"
88
+ :is-small="true"
89
+ :from-table="true"
90
+ />
91
+ </div>
92
+ </template>
93
+ </b-table-column>
94
+ </b-table>
95
+ </div>
96
+ </template>
97
+
98
+ <script>
99
+ import { mapState } from "vuex";
100
+ import AnnotationRow from "../DocumentAnnotations/AnnotationRow";
101
+ import DraggableIcon from "../../assets/images/DraggableIcon";
102
+
103
+ export default {
104
+ name: "MultiAnnotationTableOverlay",
105
+ components: {
106
+ AnnotationRow,
107
+ DraggableIcon,
108
+ },
109
+ props: {
110
+ left: {
111
+ type: Number,
112
+ required: false,
113
+ default: 0,
114
+ },
115
+ width: {
116
+ type: Number,
117
+ required: false,
118
+ default: 0,
119
+ },
120
+ },
121
+ data() {
122
+ return {
123
+ rows: [],
124
+ columns: [],
125
+ orderedAnnotations: [],
126
+ editingLabels: [],
127
+ openDropdown: null,
128
+ draggingColumnIndex: null,
129
+ isLoading: false,
130
+ };
131
+ },
132
+ computed: {
133
+ ...mapState("display", ["showAnnSetTable"]),
134
+ ...mapState("document", ["annotations"]),
135
+ },
136
+ watch: {
137
+ showAnnSetTable() {
138
+ this.handleColumns();
139
+ this.handleRows();
140
+ },
141
+ annotations() {
142
+ // if there's a change in the annotations content, we update the table
143
+ this.handleColumns();
144
+ this.handleRows();
145
+ },
146
+ columns(columns) {
147
+ if (!columns || (columns && columns.length === 0)) {
148
+ this.$store.dispatch("selection/disableSelection");
149
+ this.$store.dispatch("document/resetEditAnnotation");
150
+ this.$store.dispatch("display/showAnnSetTable", null);
151
+ }
152
+ },
153
+ },
154
+ mounted() {
155
+ this.handleColumns();
156
+ this.handleRows();
157
+ },
158
+ methods: {
159
+ getDropdownReference(column) {
160
+ return `editDropdown_${column.field}`;
161
+ },
162
+ handleColumns() {
163
+ this.columns = [];
164
+ const labelAlreadyExists = (label) => {
165
+ return (
166
+ this.columns.length > 0 &&
167
+ this.columns.find((a) => a.field === `${label.id}`) != undefined
168
+ );
169
+ };
170
+
171
+ this.showAnnSetTable.forEach((annotationSet) => {
172
+ annotationSet.labels.forEach((label) => {
173
+ if (!labelAlreadyExists(label) && label.annotations.length > 0) {
174
+ const column = {
175
+ field: `${label.id}`,
176
+ label: label,
177
+ annotationSet,
178
+ centered: false,
179
+ };
180
+ this.columns.push(column);
181
+ }
182
+ });
183
+ });
184
+ },
185
+
186
+ handleRows() {
187
+ this.rows = [];
188
+ this.orderedAnnotations = [];
189
+
190
+ this.showAnnSetTable.forEach((annotationSet) => {
191
+ let row = {};
192
+ let toAdd = false; // to not push empty labels
193
+
194
+ annotationSet.labels.forEach((label) => {
195
+ if (label.annotations.length > 0) {
196
+ row[label.id] = label.annotations[0];
197
+ this.orderedAnnotations.push(label.annotations[0]);
198
+ toAdd = true;
199
+ }
200
+ });
201
+ if (toAdd) {
202
+ this.rows.push(row);
203
+ }
204
+ });
205
+ },
206
+
207
+ async editLabel(column) {
208
+ this.$store
209
+ .dispatch(
210
+ "project/fetchLabelSetDetails",
211
+ column.annotationSet.label_set.id
212
+ )
213
+ .then(async (labelSet) => {
214
+ this.editingLabels = [];
215
+
216
+ labelSet.labels.forEach((label) => {
217
+ const dropdownLabel = {
218
+ ...label,
219
+ disabled:
220
+ this.columns.find((column) => column.label.id === label.id) !==
221
+ undefined,
222
+ };
223
+ this.editingLabels.push(dropdownLabel);
224
+ });
225
+ });
226
+ },
227
+
228
+ async changeLabel(column, label) {
229
+ this.isLoading = true;
230
+ this.closeDropdown(column);
231
+ for (let i = 0; i < this.rows.length; i++) {
232
+ const annotationToUpdate = this.rows[i][column.label.id];
233
+ await this.$store
234
+ .dispatch("document/updateAnnotation", {
235
+ annotationId: annotationToUpdate.id,
236
+ updatedValues: { label: label.id },
237
+ })
238
+ .catch((error) => {
239
+ this.$store.dispatch("document/createErrorMessage", {
240
+ error,
241
+ serverErrorMessage: this.$t("server_error"),
242
+ defaultErrorMessage: this.$t("edit_error"),
243
+ });
244
+ });
245
+ }
246
+ this.isLoading = false;
247
+ },
248
+
249
+ async deleteColumn(column) {
250
+ this.isLoading = true;
251
+ this.closeDropdown(column);
252
+
253
+ const annotationsToDelete = [];
254
+ for (let i = 0; i < this.rows.length; i++) {
255
+ const annotationToDelete = this.rows[i][column.label.id];
256
+ if (annotationToDelete && annotationToDelete.id) {
257
+ annotationsToDelete.push(annotationToDelete);
258
+ }
259
+ }
260
+
261
+ annotationsToDelete.forEach(async (annotationToDelete) => {
262
+ await this.$store
263
+ .dispatch("document/deleteAnnotation", {
264
+ annotationId: annotationToDelete.id,
265
+ annotationSet: null, // TODO: test if annotation set should be added if the feature is available again
266
+ })
267
+ .catch((error) => {
268
+ this.$store.dispatch("document/createErrorMessage", {
269
+ error,
270
+ serverErrorMessage: this.$t("server_error"),
271
+ defaultErrorMessage: this.$t("edit_error"),
272
+ });
273
+ });
274
+ });
275
+
276
+ this.isLoading = false;
277
+ },
278
+
279
+ onDropdownChange(column, open) {
280
+ this.editingLabels = [];
281
+ this.$store.dispatch("selection/disableSelection");
282
+ this.$store.dispatch("document/resetEditAnnotation");
283
+ if (open) {
284
+ if (
285
+ this.openDropdown &&
286
+ this.$refs[this.getDropdownReference(column)].length > 0
287
+ ) {
288
+ this.$refs[this.openDropdown][0].toggle();
289
+ }
290
+ this.openDropdown = this.getDropdownReference(column);
291
+ } else {
292
+ if (this.openDropdown === this.getDropdownReference(column)) {
293
+ this.openDropdown = null;
294
+ }
295
+ }
296
+ },
297
+
298
+ closeDropdown(column) {
299
+ if (
300
+ this.openDropdown &&
301
+ this.$refs[this.getDropdownReference(column)].length > 0
302
+ ) {
303
+ this.$refs[this.getDropdownReference(column)][0].toggle();
304
+ this.openDropdown = null;
305
+ }
306
+ },
307
+
308
+ columndragstart(payload) {
309
+ this.draggingColumnIndex = payload.index;
310
+ payload.event.dataTransfer.effectAllowed = "copy";
311
+ },
312
+ columndragover(payload) {
313
+ payload.event.dataTransfer.dropEffect = "copy";
314
+ payload.event.target.closest("th").classList.add("is-selected");
315
+ payload.event.preventDefault();
316
+ },
317
+ columndragleave(payload) {
318
+ payload.event.target.closest("th").classList.remove("is-selected");
319
+ payload.event.preventDefault();
320
+ },
321
+ async columndrop(payload) {
322
+ payload.event.target.closest("th").classList.remove("is-selected");
323
+ const droppedOnColumnIndex = payload.index;
324
+
325
+ const draggingColumn = this.columns[this.draggingColumnIndex];
326
+ const droppedColumn = this.columns[droppedOnColumnIndex];
327
+
328
+ await this.changeLabel(draggingColumn, droppedColumn.label);
329
+ await this.changeLabel(droppedColumn, draggingColumn.label);
330
+ },
331
+ },
332
+ };
333
+ </script>
334
+ <style
335
+ scoped
336
+ lang="scss"
337
+ src="../../assets/scss/multi_ann_table_overlay.scss"
338
+ ></style>