@konfuzio/document-validation-ui 0.1.48-dev.1 → 0.1.48-dev.3
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/dist/js/chunk-vendors.js +6 -6
- package/dist/js/chunk-vendors.js.map +1 -1
- package/jest.config.js +1 -1
- package/package.json +2 -1
- package/src/api.js +18 -8
- package/src/assets/scss/document_page.scss +10 -0
- package/src/assets/scss/theme.scss +9 -0
- package/src/components/App.vue +58 -3
- package/src/components/DocumentPage/DocumentPage.vue +42 -81
- package/src/components/DocumentPage/EditAnnotation.vue +33 -19
- package/src/components/DocumentPage/NewAnnotation.vue +13 -4
- package/src/store/document.js +11 -4
- package/src/utils/keycloak.js +38 -0
package/jest.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@konfuzio/document-validation-ui",
|
|
3
|
-
"version": "0.1.48-dev.
|
|
3
|
+
"version": "0.1.48-dev.3",
|
|
4
4
|
"repository": "git://github.com:konfuzio-ai/document-validation-ui.git",
|
|
5
5
|
"main": "dist/app.js",
|
|
6
6
|
"scripts": {
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"axios": "^1.7.4",
|
|
33
33
|
"bignumber.js": "^9.1.0",
|
|
34
34
|
"buefy": "^0.9.22",
|
|
35
|
+
"keycloak-js": "^26.0.6",
|
|
35
36
|
"konva": "^8.3.13",
|
|
36
37
|
"sass": "^1.56.0",
|
|
37
38
|
"sass-loader": "^13.1.0",
|
package/src/api.js
CHANGED
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
+
import { updateKeycloakToken } from "./utils/keycloak";
|
|
2
3
|
|
|
3
|
-
let HTTP, FILE_REQUEST, authToken, appLocale;
|
|
4
|
+
let HTTP, FILE_REQUEST, authToken, appLocale, isKeycloakAuth;
|
|
4
5
|
const DEFAULT_URL = "https://app.konfuzio.com";
|
|
5
6
|
const FILE_URL = process.env.VUE_APP_IMAGE_URL;
|
|
6
7
|
|
|
7
|
-
axios.defaults.xsrfCookieName = "csrftoken";
|
|
8
|
-
axios.defaults.xsrfHeaderName = "X-CSRFToken";
|
|
9
|
-
|
|
10
8
|
HTTP = axios.create({
|
|
11
9
|
baseURL: process.env.VUE_APP_API_URL || `${DEFAULT_URL}/api/v3/`,
|
|
12
10
|
});
|
|
@@ -20,6 +18,10 @@ const setAuthToken = (token) => {
|
|
|
20
18
|
authToken = token;
|
|
21
19
|
};
|
|
22
20
|
|
|
21
|
+
const setIsKeycloakAuth = (result) => {
|
|
22
|
+
isKeycloakAuth = result;
|
|
23
|
+
};
|
|
24
|
+
|
|
23
25
|
const setApiUrl = (url) => {
|
|
24
26
|
HTTP.defaults.baseURL = url;
|
|
25
27
|
};
|
|
@@ -32,15 +34,22 @@ const setLocale = (locale) => {
|
|
|
32
34
|
appLocale = locale;
|
|
33
35
|
};
|
|
34
36
|
|
|
35
|
-
const getInterceptorConfig = (config) => {
|
|
37
|
+
const getInterceptorConfig = async (config) => {
|
|
36
38
|
if (authToken) {
|
|
37
|
-
config.headers["Authorization"] =
|
|
38
|
-
|
|
39
|
+
config.headers["Authorization"] = `${
|
|
40
|
+
isKeycloakAuth ? "Bearer" : "Token"
|
|
41
|
+
} ${authToken}`;
|
|
39
42
|
}
|
|
43
|
+
config.headers["Accept-Language"] = `${appLocale}-${appLocale}`;
|
|
44
|
+
|
|
45
|
+
if (isKeycloakAuth) {
|
|
46
|
+
await updateKeycloakToken();
|
|
47
|
+
}
|
|
48
|
+
|
|
40
49
|
return config;
|
|
41
50
|
};
|
|
42
51
|
|
|
43
|
-
HTTP.interceptors.request.use(getInterceptorConfig, (error) => {
|
|
52
|
+
HTTP.interceptors.request.use(getInterceptorConfig, async (error) => {
|
|
44
53
|
return Promise.reject(error);
|
|
45
54
|
});
|
|
46
55
|
|
|
@@ -107,6 +116,7 @@ export default {
|
|
|
107
116
|
makeFileRequest,
|
|
108
117
|
makeGetPaginatedRequest,
|
|
109
118
|
setAuthToken,
|
|
119
|
+
setIsKeycloakAuth,
|
|
110
120
|
setLocale,
|
|
111
121
|
FILE_REQUEST,
|
|
112
122
|
DEFAULT_URL,
|
package/src/components/App.vue
CHANGED
|
@@ -19,6 +19,7 @@ import {
|
|
|
19
19
|
} from "../utils/utils";
|
|
20
20
|
import { Integrations } from "@sentry/tracing";
|
|
21
21
|
import API from "../api";
|
|
22
|
+
import { initKeycloak } from "../utils/keycloak";
|
|
22
23
|
|
|
23
24
|
export default {
|
|
24
25
|
name: "App",
|
|
@@ -98,6 +99,24 @@ export default {
|
|
|
98
99
|
required: false,
|
|
99
100
|
default: "",
|
|
100
101
|
},
|
|
102
|
+
// eslint-disable-next-line vue/prop-name-casing
|
|
103
|
+
sso_url: {
|
|
104
|
+
type: String,
|
|
105
|
+
required: false,
|
|
106
|
+
default: "",
|
|
107
|
+
},
|
|
108
|
+
// eslint-disable-next-line vue/prop-name-casing
|
|
109
|
+
sso_realm: {
|
|
110
|
+
type: String,
|
|
111
|
+
required: false,
|
|
112
|
+
default: "",
|
|
113
|
+
},
|
|
114
|
+
// eslint-disable-next-line vue/prop-name-casing
|
|
115
|
+
sso_client_id: {
|
|
116
|
+
type: String,
|
|
117
|
+
required: false,
|
|
118
|
+
default: "",
|
|
119
|
+
},
|
|
101
120
|
},
|
|
102
121
|
computed: {
|
|
103
122
|
...mapState("display", ["pageError"]),
|
|
@@ -133,7 +152,11 @@ export default {
|
|
|
133
152
|
}
|
|
134
153
|
},
|
|
135
154
|
isPublicView() {
|
|
136
|
-
if (
|
|
155
|
+
if (
|
|
156
|
+
this.userToken ||
|
|
157
|
+
this.fullMode ||
|
|
158
|
+
(this.ssoUrl && this.ssoRealm && this.ssoClientId)
|
|
159
|
+
) {
|
|
137
160
|
return false;
|
|
138
161
|
} else {
|
|
139
162
|
return true;
|
|
@@ -160,6 +183,33 @@ export default {
|
|
|
160
183
|
return null;
|
|
161
184
|
}
|
|
162
185
|
},
|
|
186
|
+
ssoUrl() {
|
|
187
|
+
if (process.env.VUE_APP_SSO_URL) {
|
|
188
|
+
return process.env.VUE_APP_SSO_URL;
|
|
189
|
+
} else if (this.sso_url) {
|
|
190
|
+
return this.sso_url;
|
|
191
|
+
} else {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
ssoRealm() {
|
|
196
|
+
if (process.env.VUE_APP_SSO_REALM) {
|
|
197
|
+
return process.env.VUE_APP_SSO_REALM;
|
|
198
|
+
} else if (this.sso_realm) {
|
|
199
|
+
return this.sso_realm;
|
|
200
|
+
} else {
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
ssoClientId() {
|
|
205
|
+
if (process.env.VUE_APP_SSO_CLIENT_ID) {
|
|
206
|
+
return process.env.VUE_APP_SSO_CLIENT_ID;
|
|
207
|
+
} else if (this.sso_client_id) {
|
|
208
|
+
return this.sso_client_id;
|
|
209
|
+
} else {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
},
|
|
163
213
|
annotationId() {
|
|
164
214
|
if (getURLValueFromHash("ann")) {
|
|
165
215
|
return getURLValueFromHash("ann");
|
|
@@ -183,7 +233,7 @@ export default {
|
|
|
183
233
|
}
|
|
184
234
|
},
|
|
185
235
|
},
|
|
186
|
-
created() {
|
|
236
|
+
async created() {
|
|
187
237
|
// Sentry config
|
|
188
238
|
if (process.env.NODE_ENV != "development") {
|
|
189
239
|
Sentry.init({
|
|
@@ -211,7 +261,12 @@ export default {
|
|
|
211
261
|
}
|
|
212
262
|
|
|
213
263
|
// api config
|
|
214
|
-
|
|
264
|
+
if (this.userToken) {
|
|
265
|
+
API.setAuthToken(this.userToken);
|
|
266
|
+
} else if (this.ssoUrl && this.ssoRealm && this.ssoClientId) {
|
|
267
|
+
await initKeycloak(this.ssoUrl, this.ssoRealm, this.ssoClientId);
|
|
268
|
+
}
|
|
269
|
+
|
|
215
270
|
API.setLocale(this.$i18n.locale);
|
|
216
271
|
|
|
217
272
|
if (this.api_url !== "") {
|
|
@@ -31,6 +31,14 @@
|
|
|
31
31
|
:container-height="scaledViewport.height"
|
|
32
32
|
/>
|
|
33
33
|
|
|
34
|
+
<div
|
|
35
|
+
v-if="showAnnotationLabel"
|
|
36
|
+
class="annotation-label"
|
|
37
|
+
:style="getAnnotationLabelPosition(showAnnotationLabel)"
|
|
38
|
+
>
|
|
39
|
+
{{ showAnnotationLabel.labelName }}
|
|
40
|
+
</div>
|
|
41
|
+
|
|
34
42
|
<AnnSetTableOptions v-if="showAnnSetTable" :page="page" />
|
|
35
43
|
|
|
36
44
|
<v-stage
|
|
@@ -78,35 +86,6 @@
|
|
|
78
86
|
)"
|
|
79
87
|
>
|
|
80
88
|
<v-group :key="'ann' + annotation.id + '-' + index">
|
|
81
|
-
<v-label
|
|
82
|
-
v-if="annotation.id == annotationId && !searchEnabled"
|
|
83
|
-
:key="`label${annotation.id}`"
|
|
84
|
-
:config="{
|
|
85
|
-
listening: false,
|
|
86
|
-
...annotationLabelRect(
|
|
87
|
-
bbox,
|
|
88
|
-
labelOfAnnotation(annotation).name
|
|
89
|
-
),
|
|
90
|
-
}"
|
|
91
|
-
>
|
|
92
|
-
<v-tag
|
|
93
|
-
:config="{
|
|
94
|
-
fill: '#1A1A1A',
|
|
95
|
-
lineJoin: 'round',
|
|
96
|
-
hitStrokeWidth: 0,
|
|
97
|
-
listening: false,
|
|
98
|
-
}"
|
|
99
|
-
/>
|
|
100
|
-
<v-text
|
|
101
|
-
:config="{
|
|
102
|
-
padding: 4,
|
|
103
|
-
text: labelOfAnnotation(annotation).name,
|
|
104
|
-
fill: 'white',
|
|
105
|
-
fontSize: 12,
|
|
106
|
-
listening: false,
|
|
107
|
-
}"
|
|
108
|
-
/>
|
|
109
|
-
</v-label>
|
|
110
89
|
<v-rect
|
|
111
90
|
v-if="!isAnnotationInEditMode(annotation.id)"
|
|
112
91
|
:config="annotationRect(bbox, annotation.id)"
|
|
@@ -142,42 +121,6 @@
|
|
|
142
121
|
</template>
|
|
143
122
|
</template>
|
|
144
123
|
</v-layer>
|
|
145
|
-
<v-layer
|
|
146
|
-
v-if="
|
|
147
|
-
showFocusedAnnotation &&
|
|
148
|
-
!isSelecting &&
|
|
149
|
-
documentAnnotationSelected.labelName !== ''
|
|
150
|
-
"
|
|
151
|
-
>
|
|
152
|
-
<v-label
|
|
153
|
-
:key="`label${documentAnnotationSelected.id}`"
|
|
154
|
-
:config="{
|
|
155
|
-
listening: false,
|
|
156
|
-
...annotationLabelRect(
|
|
157
|
-
documentAnnotationSelected.span,
|
|
158
|
-
documentAnnotationSelected.labelName
|
|
159
|
-
),
|
|
160
|
-
}"
|
|
161
|
-
>
|
|
162
|
-
<v-tag
|
|
163
|
-
:config="{
|
|
164
|
-
fill: '#1A1A1A',
|
|
165
|
-
lineJoin: 'round',
|
|
166
|
-
hitStrokeWidth: 0,
|
|
167
|
-
listening: false,
|
|
168
|
-
}"
|
|
169
|
-
/>
|
|
170
|
-
<v-text
|
|
171
|
-
:config="{
|
|
172
|
-
padding: 4,
|
|
173
|
-
text: documentAnnotationSelected.labelName,
|
|
174
|
-
fill: 'white',
|
|
175
|
-
fontSize: 12,
|
|
176
|
-
listening: false,
|
|
177
|
-
}"
|
|
178
|
-
/>
|
|
179
|
-
</v-label>
|
|
180
|
-
</v-layer>
|
|
181
124
|
<v-layer v-if="page.number === selectionPage">
|
|
182
125
|
<box-selection
|
|
183
126
|
:page="page"
|
|
@@ -337,6 +280,18 @@ export default {
|
|
|
337
280
|
this.page.number
|
|
338
281
|
);
|
|
339
282
|
},
|
|
283
|
+
showAnnotationLabel() {
|
|
284
|
+
if (
|
|
285
|
+
this.showFocusedAnnotation &&
|
|
286
|
+
!this.isSelecting &&
|
|
287
|
+
this.documentAnnotationSelected &&
|
|
288
|
+
this.documentAnnotationSelected.labelName !== ""
|
|
289
|
+
) {
|
|
290
|
+
return this.documentAnnotationSelected;
|
|
291
|
+
} else {
|
|
292
|
+
return null;
|
|
293
|
+
}
|
|
294
|
+
},
|
|
340
295
|
},
|
|
341
296
|
watch: {
|
|
342
297
|
recalculatingAnnotations(newState) {
|
|
@@ -686,22 +641,28 @@ export default {
|
|
|
686
641
|
...this.bboxToRect(this.page, bbox),
|
|
687
642
|
};
|
|
688
643
|
},
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
644
|
+
getAnnotationLabelPosition(annotation) {
|
|
645
|
+
if (annotation && this.$refs.stage) {
|
|
646
|
+
const padding = 8;
|
|
647
|
+
const maxCharacters = 10;
|
|
648
|
+
const minimumSpaceTopY = 50;
|
|
649
|
+
const rect = this.bboxToRect(this.page, annotation.span, true);
|
|
650
|
+
|
|
651
|
+
if (
|
|
652
|
+
annotation.labelName.length > maxCharacters &&
|
|
653
|
+
rect.y < minimumSpaceTopY
|
|
654
|
+
) {
|
|
655
|
+
return `left: ${rect.x}px; top: ${
|
|
656
|
+
rect.y + rect.height * 3 + padding
|
|
657
|
+
}px`;
|
|
658
|
+
} else {
|
|
659
|
+
return `left: ${rect.x}px; bottom: ${
|
|
660
|
+
this.$refs.stage.$el.clientHeight - rect.y - rect.height - padding
|
|
661
|
+
}px`;
|
|
662
|
+
}
|
|
663
|
+
} else {
|
|
664
|
+
return "";
|
|
665
|
+
}
|
|
705
666
|
},
|
|
706
667
|
closePopups() {
|
|
707
668
|
this.newAnnotation = [];
|
|
@@ -10,13 +10,18 @@
|
|
|
10
10
|
:class="[
|
|
11
11
|
'annotation-dropdown',
|
|
12
12
|
'no-padding-bottom',
|
|
13
|
+
'dropdown-full-width',
|
|
13
14
|
setsList.length === 0 ? 'no-padding-top' : '',
|
|
14
15
|
]"
|
|
15
16
|
scrollable
|
|
16
17
|
>
|
|
17
18
|
<template #trigger>
|
|
18
19
|
<b-button
|
|
19
|
-
:class="[
|
|
20
|
+
:class="[
|
|
21
|
+
'popup-input',
|
|
22
|
+
selectedSet ? '' : 'not-selected',
|
|
23
|
+
'has-right-icon',
|
|
24
|
+
]"
|
|
20
25
|
type="is-text"
|
|
21
26
|
>
|
|
22
27
|
{{
|
|
@@ -24,7 +29,9 @@
|
|
|
24
29
|
? `${selectedSet.label_set.name} ${
|
|
25
30
|
selectedSet.id
|
|
26
31
|
? numberOfAnnotationSetGroup(selectedSet)
|
|
27
|
-
:
|
|
32
|
+
: `${numberOfLabelSetGroup(selectedSet.label_set)} (${$t(
|
|
33
|
+
"new"
|
|
34
|
+
)})`
|
|
28
35
|
}`
|
|
29
36
|
: $t("select_annotation_set")
|
|
30
37
|
}}
|
|
@@ -33,6 +40,14 @@
|
|
|
33
40
|
</span>
|
|
34
41
|
</b-button>
|
|
35
42
|
</template>
|
|
43
|
+
<b-button
|
|
44
|
+
type="is-ghost"
|
|
45
|
+
:class="['add-ann-set', 'dropdown-item', 'no-icon-margin']"
|
|
46
|
+
icon-left="plus"
|
|
47
|
+
@click="openAnnotationSetCreation"
|
|
48
|
+
>
|
|
49
|
+
{{ $t("new_ann_set_title") }}
|
|
50
|
+
</b-button>
|
|
36
51
|
<b-dropdown-item
|
|
37
52
|
v-for="(set, index) in setsList"
|
|
38
53
|
:key="`${set.label_set.id}_${index}`"
|
|
@@ -41,23 +56,12 @@
|
|
|
41
56
|
>
|
|
42
57
|
<span>{{
|
|
43
58
|
`${set.label_set.name} ${
|
|
44
|
-
set.id
|
|
59
|
+
set.id
|
|
60
|
+
? numberOfAnnotationSetGroup(set)
|
|
61
|
+
: `${numberOfLabelSetGroup(set.label_set)} (${$t("new")})`
|
|
45
62
|
}`
|
|
46
63
|
}}</span>
|
|
47
64
|
</b-dropdown-item>
|
|
48
|
-
<b-button
|
|
49
|
-
type="is-ghost"
|
|
50
|
-
:class="[
|
|
51
|
-
'add-ann-set',
|
|
52
|
-
'dropdown-item',
|
|
53
|
-
'no-icon-margin',
|
|
54
|
-
setsList.length > 0 ? 'has-border' : '',
|
|
55
|
-
]"
|
|
56
|
-
icon-left="plus"
|
|
57
|
-
@click="openAnnotationSetCreation"
|
|
58
|
-
>
|
|
59
|
-
{{ $t("new_ann_set_title") }}
|
|
60
|
-
</b-button>
|
|
61
65
|
</b-dropdown>
|
|
62
66
|
<b-tooltip
|
|
63
67
|
multilined
|
|
@@ -73,11 +77,11 @@
|
|
|
73
77
|
aria-role="list"
|
|
74
78
|
:disabled="!labelsFiltered || labelsFiltered.length === 0"
|
|
75
79
|
scrollable
|
|
76
|
-
class="label-dropdown annotation-dropdown"
|
|
80
|
+
class="label-dropdown annotation-dropdown dropdown-full-width"
|
|
77
81
|
>
|
|
78
82
|
<template #trigger>
|
|
79
83
|
<b-button
|
|
80
|
-
class="popup-input"
|
|
84
|
+
class="popup-input has-right-icon"
|
|
81
85
|
:disabled="!labelsFiltered"
|
|
82
86
|
type="is-text"
|
|
83
87
|
>
|
|
@@ -166,6 +170,7 @@ export default {
|
|
|
166
170
|
]),
|
|
167
171
|
...mapGetters("document", [
|
|
168
172
|
"numberOfAnnotationSetGroup",
|
|
173
|
+
"numberOfLabelSetGroup",
|
|
169
174
|
"labelsFilteredForAnnotationCreation",
|
|
170
175
|
]),
|
|
171
176
|
...mapGetters("display", ["bboxToRect"]),
|
|
@@ -304,12 +309,21 @@ export default {
|
|
|
304
309
|
}
|
|
305
310
|
},
|
|
306
311
|
chooseLabelSet(labelSet) {
|
|
312
|
+
// check if there's already a new entry for that label set to be created
|
|
313
|
+
const existsIndex = this.setsList.findIndex((set) => {
|
|
314
|
+
return set.id === null && set.label_set.id === labelSet.id;
|
|
315
|
+
});
|
|
316
|
+
|
|
307
317
|
const newSet = {
|
|
308
318
|
label_set: labelSet,
|
|
309
319
|
labels: labelSet.labels,
|
|
310
320
|
id: null,
|
|
311
321
|
};
|
|
312
|
-
|
|
322
|
+
if (existsIndex >= 0) {
|
|
323
|
+
this.setsList[existsIndex] = newSet;
|
|
324
|
+
} else {
|
|
325
|
+
this.setsList.unshift(newSet);
|
|
326
|
+
}
|
|
313
327
|
this.selectedSet = newSet;
|
|
314
328
|
},
|
|
315
329
|
openAnnotationSetCreation() {
|
|
@@ -12,13 +12,18 @@
|
|
|
12
12
|
'annotation-dropdown',
|
|
13
13
|
'no-padding-bottom',
|
|
14
14
|
'no-padding-top',
|
|
15
|
+
'dropdown-full-width',
|
|
15
16
|
setsList.length === 0 ? 'no-padding-top' : '',
|
|
16
17
|
]"
|
|
17
18
|
scrollable
|
|
18
19
|
>
|
|
19
20
|
<template #trigger>
|
|
20
21
|
<b-button
|
|
21
|
-
:class="[
|
|
22
|
+
:class="[
|
|
23
|
+
'popup-input',
|
|
24
|
+
selectedSet ? '' : 'not-selected',
|
|
25
|
+
'has-right-icon',
|
|
26
|
+
]"
|
|
22
27
|
type="is-text"
|
|
23
28
|
>
|
|
24
29
|
{{
|
|
@@ -76,11 +81,15 @@
|
|
|
76
81
|
aria-role="list"
|
|
77
82
|
:disabled="!textFromEntities || !labels || labels.length === 0"
|
|
78
83
|
scrollable
|
|
79
|
-
class="label-dropdown annotation-dropdown"
|
|
84
|
+
class="label-dropdown annotation-dropdown dropdown-full-width"
|
|
80
85
|
>
|
|
81
86
|
<template #trigger>
|
|
82
87
|
<b-button
|
|
83
|
-
:class="[
|
|
88
|
+
:class="[
|
|
89
|
+
'popup-input',
|
|
90
|
+
selectedLabel ? '' : 'not-selected',
|
|
91
|
+
'has-right-icon',
|
|
92
|
+
]"
|
|
84
93
|
type="is-text"
|
|
85
94
|
>
|
|
86
95
|
{{
|
|
@@ -323,7 +332,7 @@ export default {
|
|
|
323
332
|
if (existsIndex >= 0) {
|
|
324
333
|
this.setsList[existsIndex] = newSet;
|
|
325
334
|
} else {
|
|
326
|
-
this.setsList.
|
|
335
|
+
this.setsList.unshift(newSet);
|
|
327
336
|
}
|
|
328
337
|
this.selectedSet = newSet;
|
|
329
338
|
},
|
package/src/store/document.js
CHANGED
|
@@ -563,9 +563,13 @@ const getters = {
|
|
|
563
563
|
let returnLabelSets = [];
|
|
564
564
|
if (state.annotationSets) {
|
|
565
565
|
state.annotationSets.forEach((annotationSet) => {
|
|
566
|
+
// last validation checks if the label set is already present in list
|
|
566
567
|
if (
|
|
567
|
-
annotationSet.id == null ||
|
|
568
|
-
|
|
568
|
+
(annotationSet.id == null ||
|
|
569
|
+
annotationSet.label_set.has_multiple_annotation_sets) &&
|
|
570
|
+
!returnLabelSets.find(
|
|
571
|
+
(set) => set.id !== null && set.id === annotationSet.label_set.id
|
|
572
|
+
)
|
|
569
573
|
) {
|
|
570
574
|
const labelSet = { ...annotationSet.label_set };
|
|
571
575
|
labelSet.labels = [...annotationSet.labels];
|
|
@@ -702,7 +706,10 @@ const getters = {
|
|
|
702
706
|
},
|
|
703
707
|
|
|
704
708
|
annotationById: (state) => (annotationId) => {
|
|
705
|
-
|
|
709
|
+
if (state.annotations) {
|
|
710
|
+
return state.annotations.find((ann) => ann.id == annotationId);
|
|
711
|
+
}
|
|
712
|
+
return null;
|
|
706
713
|
},
|
|
707
714
|
|
|
708
715
|
// Check if document is ready to be finished
|
|
@@ -950,7 +957,7 @@ const actions = {
|
|
|
950
957
|
commit("SET_PAGES", []);
|
|
951
958
|
commit("SET_DOC_ID", id);
|
|
952
959
|
},
|
|
953
|
-
setAnnotationId: ({ commit }, id) => {
|
|
960
|
+
setAnnotationId: ({ commit, dispatch, getters }, id) => {
|
|
954
961
|
commit("SET_ANNOTATION_ID", id);
|
|
955
962
|
setURLAnnotationHash(id);
|
|
956
963
|
},
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import Keycloak from "keycloak-js";
|
|
2
|
+
import API from "../api";
|
|
3
|
+
|
|
4
|
+
let keycloak;
|
|
5
|
+
|
|
6
|
+
export const initKeycloak = async (url, realm, clientId) => {
|
|
7
|
+
keycloak = new Keycloak({
|
|
8
|
+
url,
|
|
9
|
+
realm,
|
|
10
|
+
clientId,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
const authenticated = await keycloak.init({
|
|
15
|
+
onLoad: "login-required",
|
|
16
|
+
enableLogging: true,
|
|
17
|
+
});
|
|
18
|
+
if (authenticated) {
|
|
19
|
+
API.setIsKeycloakAuth(true);
|
|
20
|
+
API.setAuthToken(keycloak.token);
|
|
21
|
+
} else {
|
|
22
|
+
console.error("User is not authenticated");
|
|
23
|
+
}
|
|
24
|
+
} catch (error) {
|
|
25
|
+
console.error("Failed to initialize adapter:", error);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export const updateKeycloakToken = () => {
|
|
30
|
+
return new Promise(async (resolve, reject) => {
|
|
31
|
+
if (keycloak) {
|
|
32
|
+
const update = await keycloak.updateToken(30);
|
|
33
|
+
resolve();
|
|
34
|
+
} else {
|
|
35
|
+
reject();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
};
|