@konfuzio/document-validation-ui 0.1.17-dev.1 → 0.1.17-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/app.css +1 -1
- package/dist/index.html +1 -1
- package/dist/js/app.js +1 -1
- package/dist/js/app.js.map +1 -1
- package/package.json +1 -1
- package/src/api.js +4 -1
- package/src/assets/images/TranslateArrows.vue +24 -0
- package/src/assets/scss/document_annotations.scss +37 -0
- package/src/components/App.vue +0 -15
- package/src/components/DocumentAnnotations/AnnotationContent.vue +2 -7
- package/src/components/DocumentAnnotations/AnnotationDetails.vue +5 -28
- package/src/components/DocumentAnnotations/AnnotationRow.vue +71 -18
- package/src/components/DocumentAnnotations/AnnotationSetActionButtons.vue +3 -3
- package/src/components/DocumentAnnotations/DocumentAnnotations.cy.js +42 -2
- package/src/components/DocumentAnnotations/DocumentAnnotations.vue +7 -24
- package/src/components/DocumentEdit/DocumentEdit.cy.js +20 -18
- package/src/components/DocumentPage/DocumentPage.vue +2 -1
- package/src/locales/de.json +4 -1
- package/src/locales/en.json +4 -1
- package/src/locales/es.json +4 -1
- package/src/store/document.js +37 -22
- package/src/store/project.js +19 -1
- package/src/assets/images/UserIcon.vue +0 -8
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -3,6 +3,7 @@ import { cacheAdapterEnhancer } from "axios-extensions";
|
|
|
3
3
|
|
|
4
4
|
let HTTP, FILE_REQUEST, authToken, appLocale;
|
|
5
5
|
const DEFAULT_URL = "https://app.konfuzio.com";
|
|
6
|
+
const FILE_URL = process.env.VUE_APP_DOCUMENT_IMAGES_URL;
|
|
6
7
|
|
|
7
8
|
axios.defaults.xsrfCookieName = "csrftoken";
|
|
8
9
|
axios.defaults.xsrfHeaderName = "X-CSRFToken";
|
|
@@ -12,7 +13,7 @@ HTTP = axios.create({
|
|
|
12
13
|
});
|
|
13
14
|
|
|
14
15
|
FILE_REQUEST = axios.create({
|
|
15
|
-
baseURL:
|
|
16
|
+
baseURL: FILE_URL || `${DEFAULT_URL}`,
|
|
16
17
|
responseType: "blob",
|
|
17
18
|
adapter: cacheAdapterEnhancer(axios.defaults.adapter),
|
|
18
19
|
});
|
|
@@ -76,4 +77,6 @@ export default {
|
|
|
76
77
|
setAuthToken,
|
|
77
78
|
setLocale,
|
|
78
79
|
FILE_REQUEST,
|
|
80
|
+
DEFAULT_URL,
|
|
81
|
+
FILE_URL
|
|
79
82
|
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<svg
|
|
3
|
+
id="exchange" xmlns="http://www.w3.org/2000/svg"
|
|
4
|
+
viewBox="0 0 24 24"
|
|
5
|
+
width="24"
|
|
6
|
+
height="24"
|
|
7
|
+
>
|
|
8
|
+
<path v-if="translation" fill="#1A1A1A" d="M18,10a1,1,0,0,0-1-1H5.41l2.3-2.29A1,1,0,0,0,6.29,5.29l-4,4a1,1,0,0,0-.21,1.09A1,1,0,0,0,3,11H17A1,1,0,0,0,18,10Zm3.92,3.62A1,1,0,0,0,21,13H7a1,1,0,0,0,0,2H18.59l-2.3,2.29a1,1,0,0,0,0,1.42,1,1,0,0,0,1.42,0l4-4A1,1,0,0,0,21.92,13.62Z"></path>
|
|
9
|
+
<path v-else fill="#E1E1E1" d="M18,10a1,1,0,0,0-1-1H5.41l2.3-2.29A1,1,0,0,0,6.29,5.29l-4,4a1,1,0,0,0-.21,1.09A1,1,0,0,0,3,11H17A1,1,0,0,0,18,10Zm3.92,3.62A1,1,0,0,0,21,13H7a1,1,0,0,0,0,2H18.59l-2.3,2.29a1,1,0,0,0,0,1.42,1,1,0,0,0,1.42,0l4-4A1,1,0,0,0,21.92,13.62Z"></path>
|
|
10
|
+
</svg>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
export default {
|
|
15
|
+
name: "TranslateArrows",
|
|
16
|
+
props: {
|
|
17
|
+
translation: {
|
|
18
|
+
type: Boolean,
|
|
19
|
+
default: false,
|
|
20
|
+
required: false,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
</script>
|
|
@@ -192,6 +192,43 @@
|
|
|
192
192
|
padding: 10px 0;
|
|
193
193
|
padding-right: 4px;
|
|
194
194
|
}
|
|
195
|
+
|
|
196
|
+
.annotation-translation {
|
|
197
|
+
display: flex;
|
|
198
|
+
padding-left: 20px;
|
|
199
|
+
|
|
200
|
+
.icon {
|
|
201
|
+
display: flex;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
.translation-details {
|
|
205
|
+
display: flex;
|
|
206
|
+
flex-direction: column;
|
|
207
|
+
gap: 8px;
|
|
208
|
+
min-width: 100px;
|
|
209
|
+
text-align: left;
|
|
210
|
+
|
|
211
|
+
.translation-title {
|
|
212
|
+
font-size: 14px;
|
|
213
|
+
font-weight: 500;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.translation-info {
|
|
217
|
+
display: flex;
|
|
218
|
+
justify-content: space-between;
|
|
219
|
+
gap: 8px;
|
|
220
|
+
font-size: 12px;
|
|
221
|
+
|
|
222
|
+
.annotation-details-link {
|
|
223
|
+
color: $primary;
|
|
224
|
+
|
|
225
|
+
&:hover {
|
|
226
|
+
filter: $hover-style;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
195
232
|
}
|
|
196
233
|
|
|
197
234
|
.annotation-row-right {
|
package/src/components/App.vue
CHANGED
|
@@ -25,11 +25,6 @@ export default {
|
|
|
25
25
|
required: false,
|
|
26
26
|
default: null,
|
|
27
27
|
},
|
|
28
|
-
project: {
|
|
29
|
-
type: String,
|
|
30
|
-
required: false,
|
|
31
|
-
default: null,
|
|
32
|
-
},
|
|
33
28
|
// eslint-disable-next-line vue/prop-name-casing
|
|
34
29
|
user_token: {
|
|
35
30
|
type: String,
|
|
@@ -92,15 +87,6 @@ export default {
|
|
|
92
87
|
return null;
|
|
93
88
|
}
|
|
94
89
|
},
|
|
95
|
-
projectId() {
|
|
96
|
-
if (process.env.VUE_APP_PROJECT_ID) {
|
|
97
|
-
return process.env.VUE_APP_PROJECT_ID;
|
|
98
|
-
} else if (this.project) {
|
|
99
|
-
return this.project;
|
|
100
|
-
} else {
|
|
101
|
-
return null;
|
|
102
|
-
}
|
|
103
|
-
},
|
|
104
90
|
userToken() {
|
|
105
91
|
if (process.env.VUE_APP_GUEST_USER_TOKEN) {
|
|
106
92
|
return process.env.VUE_APP_GUEST_USER_TOKEN;
|
|
@@ -170,7 +156,6 @@ export default {
|
|
|
170
156
|
|
|
171
157
|
// document and project config
|
|
172
158
|
Promise.all([
|
|
173
|
-
this.$store.dispatch("project/setProjectId", this.projectId),
|
|
174
159
|
this.$store.dispatch("document/setDocId", this.documentId),
|
|
175
160
|
this.$store.dispatch("document/setPublicView", this.isPublicView),
|
|
176
161
|
this.$store.dispatch(
|
|
@@ -11,9 +11,8 @@
|
|
|
11
11
|
editAnnotation &&
|
|
12
12
|
editAnnotation.id === annotation.id &&
|
|
13
13
|
'error-editing',
|
|
14
|
-
isAnnotationBeingEdited && 'clicked-ann'
|
|
15
|
-
|
|
16
|
-
]"
|
|
14
|
+
isAnnotationBeingEdited && 'clicked-ann'
|
|
15
|
+
]"
|
|
17
16
|
role="textbox"
|
|
18
17
|
:contenteditable="isAnnotationBeingEdited"
|
|
19
18
|
@click="handleEditAnnotation"
|
|
@@ -75,10 +74,6 @@ export default {
|
|
|
75
74
|
"newAcceptedAnnotations",
|
|
76
75
|
"showActionError",
|
|
77
76
|
]),
|
|
78
|
-
|
|
79
|
-
isAnnotationDeleted() {
|
|
80
|
-
return this.annotation.revised && !this.annotation.is_correct;
|
|
81
|
-
},
|
|
82
77
|
isAnnotationBeingEdited() {
|
|
83
78
|
return this.isAnnotationInEditMode(this.annotation.id, this.spanIndex);
|
|
84
79
|
},
|
|
@@ -5,9 +5,8 @@
|
|
|
5
5
|
:class="[!fromTable && 'left-aligned', 'annotation-details']"
|
|
6
6
|
>
|
|
7
7
|
<div :class="['label-icon', fromTable && 'is-small']">
|
|
8
|
-
<div v-if="(created(annotation) || edited(annotation)) && !publicView">
|
|
8
|
+
<div v-if="(created(annotation) || edited(annotation)) && !isNegative(annotation) && !publicView">
|
|
9
9
|
<div
|
|
10
|
-
v-if="accepted(annotation)"
|
|
11
10
|
:class="[
|
|
12
11
|
'annotation-details-icon',
|
|
13
12
|
animate ? 'animated-ripple' : '',
|
|
@@ -16,16 +15,6 @@
|
|
|
16
15
|
>
|
|
17
16
|
<AcceptedUser />
|
|
18
17
|
</div>
|
|
19
|
-
<div
|
|
20
|
-
v-else
|
|
21
|
-
:class="[
|
|
22
|
-
'annotation-details-icon',
|
|
23
|
-
animate ? 'animated-ripple' : '',
|
|
24
|
-
'user-icon',
|
|
25
|
-
]"
|
|
26
|
-
>
|
|
27
|
-
<UserIcon />
|
|
28
|
-
</div>
|
|
29
18
|
</div>
|
|
30
19
|
<div
|
|
31
20
|
v-else-if="annotationIsNotFound(annotationSet, label) && !publicView"
|
|
@@ -34,7 +23,7 @@
|
|
|
34
23
|
<NotFoundIcon />
|
|
35
24
|
</div>
|
|
36
25
|
<div
|
|
37
|
-
v-else-if="notExtracted(annotation) && !publicView"
|
|
26
|
+
v-else-if="notExtracted(annotation) || isNegative(annotation) && !publicView"
|
|
38
27
|
:class="[
|
|
39
28
|
'annotation-details-icon',
|
|
40
29
|
animate ? 'animated-ripple' : '',
|
|
@@ -68,7 +57,7 @@
|
|
|
68
57
|
<span>{{ description }}</span>
|
|
69
58
|
</div>
|
|
70
59
|
<div
|
|
71
|
-
v-if="confidence(annotation)"
|
|
60
|
+
v-if="confidence(annotation) && !isNegative(annotation)"
|
|
72
61
|
:class="['confidence', publicView && 'tooltip-in-public-view']"
|
|
73
62
|
>
|
|
74
63
|
<span>{{ $t("confidence") }}</span
|
|
@@ -88,7 +77,6 @@
|
|
|
88
77
|
<div class="detail-icons">
|
|
89
78
|
<div v-if="created(annotation) || edited(annotation)">
|
|
90
79
|
<div
|
|
91
|
-
v-if="accepted(annotation)"
|
|
92
80
|
:class="[
|
|
93
81
|
'annotation-details-icon',
|
|
94
82
|
animate ? 'animated-ripple' : '',
|
|
@@ -97,16 +85,6 @@
|
|
|
97
85
|
>
|
|
98
86
|
<AcceptedUser />
|
|
99
87
|
</div>
|
|
100
|
-
<div
|
|
101
|
-
v-else
|
|
102
|
-
:class="[
|
|
103
|
-
'annotation-details-icon',
|
|
104
|
-
animate ? 'animated-ripple' : '',
|
|
105
|
-
'user-icon',
|
|
106
|
-
]"
|
|
107
|
-
>
|
|
108
|
-
<UserIcon />
|
|
109
|
-
</div>
|
|
110
88
|
</div>
|
|
111
89
|
<div
|
|
112
90
|
v-else-if="notExtracted(annotation)"
|
|
@@ -151,7 +129,6 @@ import CheckMark from "../../assets/images/CheckMark";
|
|
|
151
129
|
import AcceptedCheckMark from "../../assets/images/AcceptedCheckMark";
|
|
152
130
|
import QuestionMark from "../../assets/images/QuestionMark";
|
|
153
131
|
import AcceptedUser from "../../assets/images/AcceptedUser";
|
|
154
|
-
import UserIcon from "../../assets/images/UserIcon";
|
|
155
132
|
import NotFoundIcon from "../../assets/images/NotFoundIcon";
|
|
156
133
|
|
|
157
134
|
export default {
|
|
@@ -161,7 +138,6 @@ export default {
|
|
|
161
138
|
QuestionMark,
|
|
162
139
|
AcceptedCheckMark,
|
|
163
140
|
AcceptedUser,
|
|
164
|
-
UserIcon,
|
|
165
141
|
NotFoundIcon,
|
|
166
142
|
},
|
|
167
143
|
props: {
|
|
@@ -199,6 +175,7 @@ export default {
|
|
|
199
175
|
"created",
|
|
200
176
|
"edited",
|
|
201
177
|
"accepted",
|
|
178
|
+
"isNegative",
|
|
202
179
|
"getUser",
|
|
203
180
|
"annotationIsNotFound",
|
|
204
181
|
]),
|
|
@@ -225,7 +202,7 @@ export default {
|
|
|
225
202
|
},
|
|
226
203
|
methods: {
|
|
227
204
|
getText() {
|
|
228
|
-
if (this.notExtracted(this.annotation)) {
|
|
205
|
+
if (this.notExtracted(this.annotation) || this.isNegative(this.annotation)) {
|
|
229
206
|
return this.$t("not_found_in_document");
|
|
230
207
|
} else if (this.created(this.annotation)) {
|
|
231
208
|
return this.getUser(this.annotation)
|
|
@@ -37,10 +37,34 @@
|
|
|
37
37
|
>
|
|
38
38
|
<span>{{ label.name }} </span>
|
|
39
39
|
</div>
|
|
40
|
+
|
|
41
|
+
<div v-if="showTranslationsDetails" class="annotation-translation">
|
|
42
|
+
<b-tooltip
|
|
43
|
+
:animated="false"
|
|
44
|
+
position="is-bottom"
|
|
45
|
+
:close-delay="2000"
|
|
46
|
+
>
|
|
47
|
+
<div class="icon">
|
|
48
|
+
<TranslateArrows :translation="annotation.translated_string && true"/>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<template #content>
|
|
52
|
+
<div class="translation-details">
|
|
53
|
+
<div class="translation-title">
|
|
54
|
+
<span>{{ $t("translated_string_title") }}</span>
|
|
55
|
+
</div>
|
|
56
|
+
<div class="translation-info">
|
|
57
|
+
<span class="translated-string">{{ annotation.translated_string ? annotation.translated_string : $t("no_translated_string")}}</span>
|
|
58
|
+
<a v-if=!isDocumentReviewed class="annotation-details-link" @click="editAnnotationTranslation(annotation.id)">{{ annotation.translated_string ? $t("edit") : $t("add_translation")}}</a>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
</template>
|
|
62
|
+
</b-tooltip>
|
|
63
|
+
</div>
|
|
40
64
|
</div>
|
|
41
65
|
<div class="annotation-row-right">
|
|
42
66
|
<div class="annotation-content">
|
|
43
|
-
<div v-if="annotation">
|
|
67
|
+
<div v-if="annotation && !isNegative(annotation)">
|
|
44
68
|
<div
|
|
45
69
|
v-for="(span, index) in spanForEditing
|
|
46
70
|
? spanSelection
|
|
@@ -87,7 +111,7 @@
|
|
|
87
111
|
/>
|
|
88
112
|
</div>
|
|
89
113
|
</div>
|
|
90
|
-
<div
|
|
114
|
+
<div class="buttons-container">
|
|
91
115
|
<AnnotationActionButtons
|
|
92
116
|
:cancel-btn="showCancelButton()"
|
|
93
117
|
:accept-btn="showAcceptButton()"
|
|
@@ -113,7 +137,10 @@ import AnnotationDetails from "./AnnotationDetails";
|
|
|
113
137
|
import AnnotationContent from "./AnnotationContent";
|
|
114
138
|
import EmptyAnnotation from "./EmptyAnnotation";
|
|
115
139
|
import AnnotationActionButtons from "./AnnotationActionButtons";
|
|
140
|
+
import TranslateArrows from "../../assets/images/TranslateArrows";
|
|
141
|
+
|
|
116
142
|
import { isElementArray } from "../../utils/utils";
|
|
143
|
+
import api from "../../api";
|
|
117
144
|
|
|
118
145
|
export default {
|
|
119
146
|
name: "AnnotationRow",
|
|
@@ -122,6 +149,7 @@ export default {
|
|
|
122
149
|
AnnotationContent,
|
|
123
150
|
EmptyAnnotation,
|
|
124
151
|
AnnotationActionButtons,
|
|
152
|
+
TranslateArrows,
|
|
125
153
|
},
|
|
126
154
|
props: {
|
|
127
155
|
annotationSet: {
|
|
@@ -140,10 +168,6 @@ export default {
|
|
|
140
168
|
type: Boolean,
|
|
141
169
|
default: true,
|
|
142
170
|
},
|
|
143
|
-
showButtons: {
|
|
144
|
-
type: Boolean,
|
|
145
|
-
default: true,
|
|
146
|
-
},
|
|
147
171
|
fromTable: {
|
|
148
172
|
type: Boolean,
|
|
149
173
|
default: false,
|
|
@@ -175,14 +199,19 @@ export default {
|
|
|
175
199
|
"elementSelected",
|
|
176
200
|
"selectedEntities",
|
|
177
201
|
]),
|
|
202
|
+
...mapState("project", [
|
|
203
|
+
"translationsEnabled"
|
|
204
|
+
]),
|
|
178
205
|
...mapGetters("document", [
|
|
179
206
|
"isAnnotationInEditMode",
|
|
180
207
|
"annotationIsNotFound",
|
|
181
208
|
"isDocumentReviewed",
|
|
209
|
+
"isNegative"
|
|
182
210
|
]),
|
|
183
211
|
defaultSpan() {
|
|
184
212
|
if (
|
|
185
213
|
this.annotation &&
|
|
214
|
+
!this.isNegative(this.annotation) &&
|
|
186
215
|
this.annotation.span &&
|
|
187
216
|
this.annotation.span.length > 0
|
|
188
217
|
) {
|
|
@@ -200,6 +229,7 @@ export default {
|
|
|
200
229
|
isAnnotation() {
|
|
201
230
|
return (
|
|
202
231
|
this.annotation &&
|
|
232
|
+
!this.isNegative(this.annotation) &&
|
|
203
233
|
this.isAnnotationInEditMode(
|
|
204
234
|
this.annotationId(),
|
|
205
235
|
this.editAnnotation.index
|
|
@@ -222,9 +252,14 @@ export default {
|
|
|
222
252
|
this.hoveredAnnotationSet &&
|
|
223
253
|
this.hoveredAnnotationSet.type == "accept" &&
|
|
224
254
|
this.annotation &&
|
|
225
|
-
this.
|
|
255
|
+
!this.isNegative(this.annotation) &&
|
|
256
|
+
this.hoveredNotCorrectAnnotations() === this.annotation.id
|
|
226
257
|
);
|
|
227
258
|
},
|
|
259
|
+
showTranslationsDetails() {
|
|
260
|
+
// Only show translation option for filled annotations and if the feature is enabled for the project
|
|
261
|
+
return this.annotation && this.translationsEnabled && !this.publicView;
|
|
262
|
+
}
|
|
228
263
|
},
|
|
229
264
|
watch: {
|
|
230
265
|
sidebarAnnotationSelected(newSidebarAnnotationSelected) {
|
|
@@ -238,7 +273,7 @@ export default {
|
|
|
238
273
|
annotationSelected = newSidebarAnnotationSelected;
|
|
239
274
|
}
|
|
240
275
|
|
|
241
|
-
if (this.annotation && this.annotation.id === annotationSelected.id) {
|
|
276
|
+
if (this.annotation && !this.isNegative(this.annotation) && this.annotation.id === annotationSelected.id) {
|
|
242
277
|
clearTimeout(this.annotationAnimationTimeout);
|
|
243
278
|
|
|
244
279
|
let timeout;
|
|
@@ -308,12 +343,11 @@ export default {
|
|
|
308
343
|
}
|
|
309
344
|
},
|
|
310
345
|
},
|
|
311
|
-
|
|
312
346
|
methods: {
|
|
313
347
|
annotationId() {
|
|
314
348
|
if (!this.annotationSet || !this.label) return;
|
|
315
349
|
|
|
316
|
-
if (this.annotation && this.annotation.id) return this.annotation.id;
|
|
350
|
+
if (this.annotation && this.annotation.id && !this.isNegative(this.annotation)) return this.annotation.id;
|
|
317
351
|
|
|
318
352
|
let emptyAnnotationId;
|
|
319
353
|
|
|
@@ -354,10 +388,12 @@ export default {
|
|
|
354
388
|
}
|
|
355
389
|
);
|
|
356
390
|
const found = labels.find((l) => l.id === this.label.id);
|
|
357
|
-
|
|
391
|
+
const negativeAnnotations = found.annotations.find(annotation => this.isNegative(annotation));
|
|
392
|
+
|
|
393
|
+
if ((found && found.annotations.length === 0) || negativeAnnotations) return found.id;
|
|
358
394
|
return null;
|
|
359
395
|
},
|
|
360
|
-
|
|
396
|
+
hoveredNotCorrectAnnotations() {
|
|
361
397
|
// This method will change the style of Annotations in the same Label Set
|
|
362
398
|
// when the "Accept all" button is hovered
|
|
363
399
|
if (!this.hoveredAnnotationSet) return;
|
|
@@ -385,7 +421,8 @@ export default {
|
|
|
385
421
|
!this.editAnnotation &&
|
|
386
422
|
!this.isAnnotationInEditMode(this.annotationId()) &&
|
|
387
423
|
this.annotation &&
|
|
388
|
-
!this.annotation
|
|
424
|
+
!this.isNegative(this.annotation) &&
|
|
425
|
+
!this.annotation.is_correct &&
|
|
389
426
|
this.hoveredAnnotation === this.annotation.id
|
|
390
427
|
);
|
|
391
428
|
},
|
|
@@ -394,6 +431,7 @@ export default {
|
|
|
394
431
|
!this.editAnnotation &&
|
|
395
432
|
!this.isAnnotationInEditMode(this.annotationId()) &&
|
|
396
433
|
this.annotation &&
|
|
434
|
+
!this.isNegative(this.annotation) &&
|
|
397
435
|
this.hoveredAnnotation === this.annotation.id
|
|
398
436
|
);
|
|
399
437
|
},
|
|
@@ -402,7 +440,7 @@ export default {
|
|
|
402
440
|
!this.editAnnotation &&
|
|
403
441
|
this.hoveredAnnotation &&
|
|
404
442
|
!this.isAnnotationInEditMode(this.annotationId()) &&
|
|
405
|
-
!this.annotation &&
|
|
443
|
+
(!this.annotation || this.isNegative(this.annotation)) &&
|
|
406
444
|
!this.annotationIsNotFound(this.annotationSet, this.label)
|
|
407
445
|
);
|
|
408
446
|
},
|
|
@@ -416,7 +454,6 @@ export default {
|
|
|
416
454
|
},
|
|
417
455
|
showCancelButton() {
|
|
418
456
|
if (!this.editAnnotation || this.isLoading) return;
|
|
419
|
-
|
|
420
457
|
if (this.isAnnotationInEditMode(this.annotationId())) {
|
|
421
458
|
return true;
|
|
422
459
|
}
|
|
@@ -457,7 +494,7 @@ export default {
|
|
|
457
494
|
|
|
458
495
|
// Verify if we are editing a filled or empty annotation
|
|
459
496
|
if (
|
|
460
|
-
this.annotation &&
|
|
497
|
+
this.annotation && !this.isNegative(this.annotation) &&
|
|
461
498
|
(this.showAcceptButton() ||
|
|
462
499
|
this.showDeclineButton() ||
|
|
463
500
|
this.isAnnotationInEditMode(
|
|
@@ -486,7 +523,7 @@ export default {
|
|
|
486
523
|
|
|
487
524
|
this.saveAnnotationChanges(spans, decline);
|
|
488
525
|
} else if (
|
|
489
|
-
!this.annotation &&
|
|
526
|
+
(!this.annotation || this.isNegative(this.annotation)) &&
|
|
490
527
|
this.isAnnotationInEditMode(this.annotationId())
|
|
491
528
|
) {
|
|
492
529
|
this.saveEmptyAnnotationChanges();
|
|
@@ -582,9 +619,16 @@ export default {
|
|
|
582
619
|
};
|
|
583
620
|
}
|
|
584
621
|
this.isLoading = true;
|
|
622
|
+
let negativeAnnotationId;
|
|
623
|
+
|
|
624
|
+
// check if the annotation to create comes from a negative annotation
|
|
625
|
+
// so we can create the new one and remove the negative one from the annotations array
|
|
626
|
+
if(this.isNegative(this.annotation)) {
|
|
627
|
+
negativeAnnotationId = this.annotation.id;
|
|
628
|
+
}
|
|
585
629
|
|
|
586
630
|
this.$store
|
|
587
|
-
.dispatch("document/createAnnotation", annotationToCreate)
|
|
631
|
+
.dispatch("document/createAnnotation", {annotation: annotationToCreate, negativeAnnotationId: negativeAnnotationId})
|
|
588
632
|
.catch((error) => {
|
|
589
633
|
this.$store.dispatch("document/createErrorMessage", {
|
|
590
634
|
error,
|
|
@@ -652,6 +696,15 @@ export default {
|
|
|
652
696
|
});
|
|
653
697
|
}
|
|
654
698
|
},
|
|
699
|
+
editAnnotationTranslation(annotationId) {
|
|
700
|
+
if(!annotationId) return;
|
|
701
|
+
|
|
702
|
+
const baseUrl = api.FILE_URL ? api.FILE_URL : api.DEFAULT_URL;
|
|
703
|
+
|
|
704
|
+
const annotationDetailsUrl = `${baseUrl}/admin/server/sequenceannotation/${annotationId}/change/`;
|
|
705
|
+
|
|
706
|
+
window.open(annotationDetailsUrl, "_blank");
|
|
707
|
+
}
|
|
655
708
|
},
|
|
656
709
|
};
|
|
657
710
|
</script>
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
<b-button
|
|
28
28
|
type="is-primary"
|
|
29
29
|
class="accept-all-btn"
|
|
30
|
-
:disabled="
|
|
30
|
+
:disabled="numberOfNotCorrectAnnotationsInAnnotationSet === 0"
|
|
31
31
|
@click.stop="acceptAllPending"
|
|
32
32
|
>
|
|
33
33
|
{{ $t("accept_group") }} ({{
|
|
34
|
-
|
|
34
|
+
numberOfNotCorrectAnnotationsInAnnotationSet
|
|
35
35
|
}})
|
|
36
36
|
</b-button>
|
|
37
37
|
</div>
|
|
@@ -49,7 +49,7 @@ export default {
|
|
|
49
49
|
type: Number,
|
|
50
50
|
default: 0,
|
|
51
51
|
},
|
|
52
|
-
|
|
52
|
+
numberOfNotCorrectAnnotationsInAnnotationSet: {
|
|
53
53
|
type: Number,
|
|
54
54
|
default: 0,
|
|
55
55
|
},
|
|
@@ -144,7 +144,7 @@ describe("Document Annotations", () => {
|
|
|
144
144
|
cy.get("#document-annotations")
|
|
145
145
|
.find(".label")
|
|
146
146
|
.find(".annotation-row")
|
|
147
|
-
.find(".
|
|
147
|
+
.find(".annotation")
|
|
148
148
|
.each(($row) => {
|
|
149
149
|
cy.wrap($row)
|
|
150
150
|
.trigger("mouseover");
|
|
@@ -296,7 +296,7 @@ describe("Document Annotations", () => {
|
|
|
296
296
|
cy.get("#document-annotations")
|
|
297
297
|
.find(".label")
|
|
298
298
|
.find(".annotation-row")
|
|
299
|
-
.find(".
|
|
299
|
+
.find(".annotation")
|
|
300
300
|
.first()
|
|
301
301
|
.then(($element) => {
|
|
302
302
|
const annotationId = $element[0].id;
|
|
@@ -399,4 +399,44 @@ describe("Document Annotations", () => {
|
|
|
399
399
|
cy.wait("@deleteMissingAnnotation").its("response.statusCode").should("eq", 204);
|
|
400
400
|
});
|
|
401
401
|
});
|
|
402
|
+
|
|
403
|
+
it("shows details regarding translated strings if they are enabled for the project", () => {
|
|
404
|
+
cy.getStore("project").then($project => {
|
|
405
|
+
if($project.translationsEnabled) {
|
|
406
|
+
cy.getStore("document").then($document => {
|
|
407
|
+
if($document.annotations.length > 0) {
|
|
408
|
+
cy.get("#document-annotations")
|
|
409
|
+
.find(".labels")
|
|
410
|
+
.find(".label")
|
|
411
|
+
.find(".annotation-row")
|
|
412
|
+
.find(".annotation-row-left")
|
|
413
|
+
.find(".annotation-translation")
|
|
414
|
+
.first()
|
|
415
|
+
.find(".icon")
|
|
416
|
+
.should("be.visible");
|
|
417
|
+
|
|
418
|
+
cy.get("#document-annotations")
|
|
419
|
+
.find(".labels")
|
|
420
|
+
.find(".label")
|
|
421
|
+
.find(".annotation-row")
|
|
422
|
+
.find(".annotation-row-left")
|
|
423
|
+
.find(".annotation-translation")
|
|
424
|
+
.first()
|
|
425
|
+
.trigger("mouseenter");
|
|
426
|
+
|
|
427
|
+
cy.get("#document-annotations")
|
|
428
|
+
.find(".labels")
|
|
429
|
+
.find(".label")
|
|
430
|
+
.find(".annotation-row")
|
|
431
|
+
.find(".annotation-row-left")
|
|
432
|
+
.find(".annotation-translation")
|
|
433
|
+
.first()
|
|
434
|
+
.find(".tooltip-content")
|
|
435
|
+
.find(".translation-details")
|
|
436
|
+
.should("be.visible");
|
|
437
|
+
}
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
})
|
|
441
|
+
});
|
|
402
442
|
});
|
|
@@ -67,10 +67,10 @@
|
|
|
67
67
|
>
|
|
68
68
|
<AnnotationSetActionButtons
|
|
69
69
|
:number-of-empty-labels-in-annotation-set="
|
|
70
|
-
|
|
70
|
+
emptyLabels(annotationSet).length
|
|
71
71
|
"
|
|
72
|
-
:number-of-
|
|
73
|
-
|
|
72
|
+
:number-of-not-correct-annotations-in-annotation-set="
|
|
73
|
+
notCorrectAnnotations(annotationSet).length
|
|
74
74
|
"
|
|
75
75
|
@mark-all-empty-missing="
|
|
76
76
|
markAnnotationsAsMissing(null, null, annotationSet, true)
|
|
@@ -110,7 +110,7 @@
|
|
|
110
110
|
|
|
111
111
|
<div v-if="annotationSet.labels.length === 0" class="no-labels">
|
|
112
112
|
<span> {{ $t("no_labels_in_set") }}</span>
|
|
113
|
-
<span v-if="!publicView" v-html="$t('link_to_add_labels')"></span>
|
|
113
|
+
<span v-if="!publicView && !isDocumentReviewed" v-html="$t('link_to_add_labels')"></span>
|
|
114
114
|
</div>
|
|
115
115
|
|
|
116
116
|
<div
|
|
@@ -169,8 +169,8 @@ export default {
|
|
|
169
169
|
...mapGetters("category", ["category"]),
|
|
170
170
|
...mapGetters("document", [
|
|
171
171
|
"numberOfAnnotationSetGroup",
|
|
172
|
-
"
|
|
173
|
-
"
|
|
172
|
+
"emptyLabels",
|
|
173
|
+
"notCorrectAnnotations",
|
|
174
174
|
"annotationSetsToShowInList",
|
|
175
175
|
"annotationSetsInTable",
|
|
176
176
|
"isDocumentReviewed",
|
|
@@ -424,26 +424,9 @@ export default {
|
|
|
424
424
|
} else if (annotationSet && markAllMissing) {
|
|
425
425
|
// mark all annotations as missing in annotation set
|
|
426
426
|
|
|
427
|
-
const allEmptyLabels = annotationSet.labels.filter(
|
|
428
|
-
(label) => label.annotations.length === 0
|
|
429
|
-
);
|
|
430
|
-
|
|
431
427
|
// Check if any of the empty annotations was already marked as missing individually
|
|
432
428
|
// and remove them
|
|
433
|
-
const toMarkAsMissing =
|
|
434
|
-
|
|
435
|
-
allEmptyLabels.map((label) => {
|
|
436
|
-
const found = this.missingAnnotations.find(
|
|
437
|
-
(l) =>
|
|
438
|
-
l.label === label.id &&
|
|
439
|
-
l.annotation_set === annotationSet.id &&
|
|
440
|
-
l.label_set === annotationSet.label_set.id
|
|
441
|
-
);
|
|
442
|
-
|
|
443
|
-
if (!found) {
|
|
444
|
-
toMarkAsMissing.push(label);
|
|
445
|
-
}
|
|
446
|
-
});
|
|
429
|
+
const toMarkAsMissing = this.emptyLabels(annotationSet);
|
|
447
430
|
|
|
448
431
|
missing = toMarkAsMissing.map((label) => {
|
|
449
432
|
return {
|