@konfuzio/document-validation-ui 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/.eslintrc.js +11 -0
  2. package/.prettierrc.json +1 -0
  3. package/LICENSE +21 -0
  4. package/README.md +13 -0
  5. package/dist/css/app.0c8973f8.css +1 -0
  6. package/dist/css/chunk-vendors.053b6b6e.css +5 -0
  7. package/dist/favicon.ico +0 -0
  8. package/dist/index.html +1 -0
  9. package/dist/js/app.17fe48c4.js +2 -0
  10. package/dist/js/app.17fe48c4.js.map +1 -0
  11. package/dist/js/chunk-vendors.a48fca3f.js +47 -0
  12. package/dist/js/chunk-vendors.a48fca3f.js.map +1 -0
  13. package/jest.config.js +4 -0
  14. package/package.json +60 -0
  15. package/src/.DS_Store +0 -0
  16. package/src/api.js +49 -0
  17. package/src/assets/images/AcceptedCheckMark.vue +8 -0
  18. package/src/assets/images/AcceptedUser.vue +8 -0
  19. package/src/assets/images/ActionIcon.vue +60 -0
  20. package/src/assets/images/ArrowDownKey.vue +11 -0
  21. package/src/assets/images/ArrowUpKey.vue +11 -0
  22. package/src/assets/images/CategoryIconImg.vue +13 -0
  23. package/src/assets/images/CheckMark.vue +8 -0
  24. package/src/assets/images/EditDocIcon.vue +12 -0
  25. package/src/assets/images/EmptyStateImg.vue +129 -0
  26. package/src/assets/images/ErrorIcon.vue +28 -0
  27. package/src/assets/images/EyeIcon.vue +11 -0
  28. package/src/assets/images/FileNameNotSavedImage.vue +26 -0
  29. package/src/assets/images/FileNameSavedImage.vue +14 -0
  30. package/src/assets/images/FitZoomIcon.vue +16 -0
  31. package/src/assets/images/KeyboardIcon.vue +16 -0
  32. package/src/assets/images/MinusIcon.vue +13 -0
  33. package/src/assets/images/NotOptimizedIllustration.vue +651 -0
  34. package/src/assets/images/PlusIcon.vue +13 -0
  35. package/src/assets/images/QuestionMark.vue +12 -0
  36. package/src/assets/images/ServerImage.vue +63 -0
  37. package/src/assets/images/SplitLines.vue +18 -0
  38. package/src/assets/images/SplitZigZag.vue +16 -0
  39. package/src/assets/images/StatusImg.vue +14 -0
  40. package/src/assets/images/UserIcon.vue +8 -0
  41. package/src/assets/scss/annotation_details.scss +126 -0
  42. package/src/assets/scss/categorize_modal.scss +42 -0
  43. package/src/assets/scss/choose_label_set_modal.scss +62 -0
  44. package/src/assets/scss/document_action_bar.scss +37 -0
  45. package/src/assets/scss/document_annotations.scss +472 -0
  46. package/src/assets/scss/document_category.scss +80 -0
  47. package/src/assets/scss/document_dashboard.scss +47 -0
  48. package/src/assets/scss/document_dataset_status.scss +46 -0
  49. package/src/assets/scss/document_edit.scss +431 -0
  50. package/src/assets/scss/document_error.scss +81 -0
  51. package/src/assets/scss/document_handover.scss +200 -0
  52. package/src/assets/scss/document_name.scss +62 -0
  53. package/src/assets/scss/document_page.scss +8 -0
  54. package/src/assets/scss/document_thumbnails.scss +41 -0
  55. package/src/assets/scss/document_toolbar.scss +89 -0
  56. package/src/assets/scss/document_top_bar.scss +139 -0
  57. package/src/assets/scss/document_viewport_modal.scss +25 -0
  58. package/src/assets/scss/documents_list.scss +130 -0
  59. package/src/assets/scss/empty_state.scss +34 -0
  60. package/src/assets/scss/extracting_data.scss +35 -0
  61. package/src/assets/scss/imports.scss +1 -0
  62. package/src/assets/scss/main.scss +24 -0
  63. package/src/assets/scss/multi_ann_table_popup.scss +12 -0
  64. package/src/assets/scss/new_annotation.scss +86 -0
  65. package/src/assets/scss/scrolling_document.scss +19 -0
  66. package/src/assets/scss/variables.scss +696 -0
  67. package/src/components/App.vue +112 -0
  68. package/src/components/DocumentAnnotations/ActionButtons.vue +237 -0
  69. package/src/components/DocumentAnnotations/AnnotationContent.vue +249 -0
  70. package/src/components/DocumentAnnotations/AnnotationDetails.vue +292 -0
  71. package/src/components/DocumentAnnotations/AnnotationRow.vue +616 -0
  72. package/src/components/DocumentAnnotations/CategorizeModal.vue +159 -0
  73. package/src/components/DocumentAnnotations/ChooseLabelSetModal.vue +155 -0
  74. package/src/components/DocumentAnnotations/DocumentAnnotations.vue +502 -0
  75. package/src/components/DocumentAnnotations/DocumentLabel.vue +148 -0
  76. package/src/components/DocumentAnnotations/EmptyAnnotation.vue +222 -0
  77. package/src/components/DocumentAnnotations/EmptyState.vue +21 -0
  78. package/src/components/DocumentAnnotations/ExtractingData.vue +29 -0
  79. package/src/components/DocumentAnnotations/LoadingAnnotations.vue +43 -0
  80. package/src/components/DocumentAnnotations/LoadingLabels.vue +43 -0
  81. package/src/components/DocumentAnnotations/RejectedLabels.vue +96 -0
  82. package/src/components/DocumentAnnotations/index.js +8 -0
  83. package/src/components/DocumentCategory.vue +156 -0
  84. package/src/components/DocumentDashboard.vue +159 -0
  85. package/src/components/DocumentEdit/DocumentEdit.vue +279 -0
  86. package/src/components/DocumentEdit/EditPages.vue +213 -0
  87. package/src/components/DocumentEdit/EditSidebar.vue +118 -0
  88. package/src/components/DocumentEdit/SplitOverview.vue +182 -0
  89. package/src/components/DocumentEdit/index.js +4 -0
  90. package/src/components/DocumentError.vue +53 -0
  91. package/src/components/DocumentPage/ActionBar.vue +48 -0
  92. package/src/components/DocumentPage/BoxSelection.vue +149 -0
  93. package/src/components/DocumentPage/DocumentPage.vue +517 -0
  94. package/src/components/DocumentPage/DocumentToolbar.vue +145 -0
  95. package/src/components/DocumentPage/DummyPage.vue +53 -0
  96. package/src/components/DocumentPage/MultiAnnSelection.vue +302 -0
  97. package/src/components/DocumentPage/MultiAnnotationTablePopup.vue +253 -0
  98. package/src/components/DocumentPage/NewAnnotation.vue +283 -0
  99. package/src/components/DocumentPage/ScrollingDocument.vue +108 -0
  100. package/src/components/DocumentPage/ScrollingPage.vue +184 -0
  101. package/src/components/DocumentPage/index.js +5 -0
  102. package/src/components/DocumentThumbnails/DocumentThumbnails.vue +92 -0
  103. package/src/components/DocumentThumbnails/LoadingThumbnail.vue +25 -0
  104. package/src/components/DocumentThumbnails/index.js +1 -0
  105. package/src/components/DocumentTopBar/DocumentDatasetStatus.vue +103 -0
  106. package/src/components/DocumentTopBar/DocumentHandover.vue +202 -0
  107. package/src/components/DocumentTopBar/DocumentName.vue +224 -0
  108. package/src/components/DocumentTopBar/DocumentTopBar.vue +144 -0
  109. package/src/components/DocumentTopBar/DocumentTopBarButtons.vue +148 -0
  110. package/src/components/DocumentTopBar/KeyboardActionsDescription.vue +71 -0
  111. package/src/components/DocumentTopBar/index.js +5 -0
  112. package/src/components/DocumentsList/DocumentsList.vue +126 -0
  113. package/src/components/DocumentsList/index.js +1 -0
  114. package/src/components/ErrorMessage.vue +40 -0
  115. package/src/components/NotOptimizedViewportModal.vue +54 -0
  116. package/src/constants.js +4 -0
  117. package/src/directives/scroll.js +28 -0
  118. package/src/i18n.js +23 -0
  119. package/src/locales/de.json +114 -0
  120. package/src/locales/en.json +114 -0
  121. package/src/locales/es.json +113 -0
  122. package/src/main.js +87 -0
  123. package/src/store/category.js +193 -0
  124. package/src/store/display.js +238 -0
  125. package/src/store/document.js +1057 -0
  126. package/src/store/edit.js +210 -0
  127. package/src/store/index.js +22 -0
  128. package/src/store/project.js +95 -0
  129. package/src/store/selection.js +179 -0
  130. package/src/utils/utils.js +3 -0
  131. package/vue.config.js +13 -0
@@ -0,0 +1,112 @@
1
+ <template>
2
+ <div class="app-container">
3
+ <DocumentsList />
4
+ <DocumentDashboard />
5
+ </div>
6
+ </template>
7
+ <script>
8
+ import DocumentDashboard from "./DocumentDashboard";
9
+ import { DocumentsList } from "./DocumentsList";
10
+ import API from "../api";
11
+
12
+ export default {
13
+ name: "App",
14
+ components: {
15
+ DocumentsList,
16
+ DocumentDashboard,
17
+ },
18
+ props: {
19
+ document: {
20
+ type: String,
21
+ required: false,
22
+ },
23
+ project: {
24
+ type: String,
25
+ required: false,
26
+ },
27
+ user_token: {
28
+ type: String,
29
+ required: false,
30
+ },
31
+ full_mode: {
32
+ type: String,
33
+ required: false,
34
+ },
35
+ locale: { type: String, required: false },
36
+ },
37
+ computed: {
38
+ documentId() {
39
+ if (process.env.VUE_APP_DOCUMENT_ID) {
40
+ return process.env.VUE_APP_DOCUMENT_ID;
41
+ } else if (this.document) {
42
+ return this.document;
43
+ } else {
44
+ return null;
45
+ }
46
+ },
47
+ projectId() {
48
+ if (process.env.VUE_APP_PROJECT_ID) {
49
+ return process.env.VUE_APP_PROJECT_ID;
50
+ } else if (this.project) {
51
+ return this.project;
52
+ } else {
53
+ return null;
54
+ }
55
+ },
56
+ userToken() {
57
+ if (process.env.VUE_APP_GUEST_USER_TOKEN) {
58
+ return process.env.VUE_APP_GUEST_USER_TOKEN;
59
+ } else if (this.user_token) {
60
+ return this.user_token;
61
+ } else {
62
+ return null;
63
+ }
64
+ },
65
+ isPublicView() {
66
+ if (
67
+ process.env.VUE_APP_GUEST_USER_TOKEN ||
68
+ this.user_token ||
69
+ (this.full_mode && this.full_mode === "true")
70
+ ) {
71
+ return false;
72
+ } else {
73
+ return true;
74
+ }
75
+ },
76
+ },
77
+ created() {
78
+ // locale config
79
+ if (this.locale && this.locale !== "") {
80
+ this.$i18n.locale = this.locale;
81
+ }
82
+
83
+ // user token config
84
+ API.setAuthToken(this.userToken);
85
+
86
+ // document and project config
87
+ Promise.all([
88
+ this.$store.dispatch("project/setProjectId", this.projectId),
89
+ this.$store.dispatch("document/setDocId", this.documentId),
90
+ this.$store.dispatch("document/setPublicView", this.isPublicView),
91
+ ]).finally(() => {
92
+ this.$store.dispatch("document/fetchDocument");
93
+ });
94
+
95
+ // Add observer for class added to HTML tag when Buefy modals are mounted
96
+ const htmlTag = document.documentElement;
97
+ const observer = new MutationObserver(function (mutations) {
98
+ mutations.forEach(function (mutation) {
99
+ if (mutation.attributeName === "class") {
100
+ const classToRemove = "is-clipped";
101
+ if (mutation.target.classList.contains(classToRemove)) {
102
+ htmlTag.classList.remove(classToRemove);
103
+ }
104
+ }
105
+ });
106
+ });
107
+ observer.observe(htmlTag, { attributes: true });
108
+ },
109
+ };
110
+ </script>
111
+
112
+ <style lang="scss" src="../assets/scss/main.scss"></style>
@@ -0,0 +1,237 @@
1
+ <template>
2
+ <div class="action-buttons">
3
+ <!-- loading -->
4
+ <div v-if="isLoading && !finishReviewBtn">
5
+ <b-notification :closable="false" class="loading-background">
6
+ <b-loading :active="isLoading" :is-full-page="loadingOnFullPage">
7
+ <b-icon icon="spinner" class="fa-spin loading-icon-size spinner" />
8
+ </b-loading>
9
+ </b-notification>
10
+ </div>
11
+
12
+ <!-- save button -->
13
+ <b-button
14
+ v-if="saveBtn && !isLoading"
15
+ :class="[
16
+ 'annotation-save-btn text-btn',
17
+ actionBar && 'action-bar-save-btn',
18
+ ]"
19
+ type="is-primary"
20
+ @click.stop="save"
21
+ >
22
+ {{ $t("save") }}
23
+ </b-button>
24
+
25
+ <!-- cancel button -->
26
+ <b-button
27
+ v-if="cancelBtn && !isLoading"
28
+ class="is-small annotation-cancel-btn"
29
+ icon-left="xmark"
30
+ @click.stop="cancel"
31
+ />
32
+
33
+ <!-- decline button -->
34
+ <div
35
+ v-if="declineBtn && !isLoading && !saveBtn && !cancelBtn"
36
+ class="reject-decline-button-container"
37
+ >
38
+ <b-button
39
+ type="is-ghost"
40
+ class="reject-decline-btn decline-btn"
41
+ @click.stop="decline"
42
+ >
43
+ {{ $t("decline") }}
44
+ </b-button>
45
+ </div>
46
+
47
+ <!-- accept button -->
48
+ <b-button
49
+ v-if="acceptBtn && !isLoading && !saveBtn && !cancelBtn"
50
+ class="annotation-accept-btn"
51
+ type="is-primary"
52
+ @click.stop="accept"
53
+ >
54
+ {{ $t("accept") }}
55
+ </b-button>
56
+
57
+ <!-- reject button -->
58
+ <div
59
+ v-if="showReject && !isLoading && !cancelBtn && !saveBtn"
60
+ class="reject-decline-button-container"
61
+ >
62
+ <b-button
63
+ type="is-ghost"
64
+ class="reject-decline-btn reject-btn"
65
+ @click.stop="reject"
66
+ >
67
+ {{ $t("reject_label") }}
68
+ </b-button>
69
+ </div>
70
+
71
+ <!-- reject all labels -->
72
+ <div
73
+ v-if="
74
+ !publicView && rejectAllEmptyBtn && !isLoading && !cancelBtn && !saveBtn
75
+ "
76
+ class="reject-decline-button-container reject-all"
77
+ @mouseenter="mouseenterAnnotationSet('reject')"
78
+ @mouseleave="mouseleaveAnnotationSet"
79
+ >
80
+ <b-button
81
+ type="is-ghost"
82
+ class="reject-decline-btn reject-btn reject-all-btn"
83
+ :disabled="emptyLabelsLength(annotationSet) === 0"
84
+ @click.stop="rejectAllEmpty"
85
+ >
86
+ {{ $t("reject_all_empty") }} ({{ emptyLabelsLength(annotationSet) }})
87
+ </b-button>
88
+ </div>
89
+
90
+ <!-- accept all pending annotations -->
91
+ <div
92
+ v-if="!publicView && acceptAllBtn && !isLoading"
93
+ class="accept-all"
94
+ @mouseenter="mouseenterAnnotationSet('accept')"
95
+ @mouseleave="mouseleaveAnnotationSet"
96
+ >
97
+ <b-button
98
+ type="is-primary"
99
+ class="accept-all-btn"
100
+ :disabled="annotationsWithPendingReviewLength(annotationSet) === 0"
101
+ @click.stop="acceptGroup"
102
+ >
103
+ {{ $t("accept_group") }} ({{
104
+ annotationsWithPendingReviewLength(annotationSet)
105
+ }})
106
+ </b-button>
107
+ </div>
108
+
109
+ <!-- finish review button -->
110
+ <b-button
111
+ v-if="finishReviewBtn"
112
+ :class="['finish-review-btn', 'text-btn']"
113
+ type="is-primary"
114
+ :disabled="finishDisabled"
115
+ @click.stop="finishReview"
116
+ >
117
+ <span v-if="!isLoading">
118
+ {{ $t("finish_review") }}
119
+ </span>
120
+
121
+ <div v-else>
122
+ <b-notification :closable="false" :class="['loading-background']">
123
+ <b-loading :active="isLoading" :is-full-page="loadingOnFullPage">
124
+ <b-icon icon="spinner" class="fa-spin loading-icon-size spinner" />
125
+ </b-loading>
126
+ </b-notification>
127
+ </div>
128
+ </b-button>
129
+ </div>
130
+ </template>
131
+ <script>
132
+ import { mapState, mapGetters } from "vuex";
133
+ export default {
134
+ name: "ActionButtons",
135
+ props: {
136
+ saveBtn: {
137
+ type: Boolean,
138
+ },
139
+ cancelBtn: {
140
+ type: Boolean,
141
+ },
142
+ showReject: {
143
+ type: Boolean,
144
+ },
145
+ isLoading: {
146
+ type: Boolean,
147
+ },
148
+ acceptBtn: {
149
+ type: Boolean,
150
+ },
151
+ finishReviewBtn: {
152
+ type: Boolean,
153
+ },
154
+ finishDisabled: {
155
+ type: Boolean,
156
+ },
157
+ handleReject: {
158
+ type: Function,
159
+ default: null,
160
+ },
161
+ rejectAllEmptyBtn: {
162
+ type: Boolean,
163
+ },
164
+ annotationSet: {
165
+ type: Object,
166
+ default: null,
167
+ },
168
+ acceptAllBtn: {
169
+ type: Boolean,
170
+ },
171
+ declineBtn: {
172
+ type: Boolean,
173
+ },
174
+ actionBar: {
175
+ type: Boolean,
176
+ required: false,
177
+ },
178
+ },
179
+ data() {
180
+ return {
181
+ loadingOnFullPage: false,
182
+ };
183
+ },
184
+ computed: {
185
+ ...mapState("document", ["publicView", "missingAnnotations"]),
186
+ ...mapGetters("document", [
187
+ "emptyLabelsLength",
188
+ "annotationsWithPendingReviewLength",
189
+ ]),
190
+ },
191
+ methods: {
192
+ save() {
193
+ this.$emit("save");
194
+ },
195
+ cancel() {
196
+ this.$emit("cancel");
197
+ },
198
+ accept() {
199
+ this.$emit("accept");
200
+ },
201
+ reject() {
202
+ this.$emit("reject");
203
+ },
204
+ mouseenterAnnotationSet(type) {
205
+ if (type == "reject") {
206
+ this.$emit("hover-annotation-set-to-reject");
207
+ }
208
+
209
+ if (type == "accept") {
210
+ this.$emit("hover-annotation-set-to-accept");
211
+ }
212
+ },
213
+ mouseleaveAnnotationSet() {
214
+ this.$emit("leave-annotation-set-to-accept");
215
+ this.$emit("leave-annotation-set-to-reject");
216
+ },
217
+ rejectAllEmpty() {
218
+ this.$emit("reject-all-empty");
219
+ },
220
+ finishReview() {
221
+ this.$emit("finish-review");
222
+ },
223
+ acceptGroup() {
224
+ this.$emit("accept-group");
225
+ },
226
+ decline() {
227
+ this.$emit("decline");
228
+ },
229
+ },
230
+ };
231
+ </script>
232
+
233
+ <style
234
+ scoped
235
+ lang="scss"
236
+ src="../../assets/scss/document_annotations.scss"
237
+ ></style>
@@ -0,0 +1,249 @@
1
+ <template>
2
+ <div :id="annotation.id" ref="annotation" class="annotation">
3
+ <span
4
+ v-if="!publicView"
5
+ :id="annotation.id"
6
+ ref="contentEditable"
7
+ :class="[
8
+ 'annotation-value',
9
+ isLoading && 'saving-changes',
10
+ showActionError &&
11
+ editAnnotation &&
12
+ editAnnotation.id === annotation.id &&
13
+ 'error-editing',
14
+ isAnnotationBeingEdited && 'clicked',
15
+ ]"
16
+ role="textbox"
17
+ :contenteditable="isAnnotationBeingEdited"
18
+ @click="handleEditAnnotation"
19
+ @paste="handlePaste"
20
+ @keypress.enter="saveAnnotationChanges"
21
+ >
22
+ {{ span.offset_string }}
23
+ </span>
24
+ <span v-else class="annotation-value">
25
+ {{ span.offset_string }}
26
+ </span>
27
+ </div>
28
+ </template>
29
+
30
+ <script>
31
+ import { mapGetters, mapState } from "vuex";
32
+
33
+ /**
34
+ * This component is responsible for managing filled annotations.
35
+ */
36
+ export default {
37
+ name: "AnnotationContent",
38
+ props: {
39
+ annotation: {
40
+ type: Object,
41
+ required: true,
42
+ },
43
+ span: {
44
+ required: true,
45
+ },
46
+ spanIndex: {
47
+ type: Number,
48
+ required: true,
49
+ },
50
+ label: {
51
+ type: Object,
52
+ },
53
+ annotationSet: {
54
+ type: Object,
55
+ },
56
+ saveChanges: {
57
+ type: Boolean,
58
+ required: false,
59
+ },
60
+ },
61
+ data() {
62
+ return {
63
+ isLoading: false,
64
+ };
65
+ },
66
+ computed: {
67
+ ...mapGetters("document", [
68
+ "isAnnotationInEditMode",
69
+ "pageAtIndex",
70
+ "getTextFromEntities",
71
+ ]),
72
+ ...mapGetters("display", ["bboxToRect"]),
73
+ ...mapGetters("selection", ["isValueArray"]),
74
+ ...mapState("selection", ["spanSelection"]),
75
+ ...mapState("document", [
76
+ "editAnnotation",
77
+ "publicView",
78
+ "annotations",
79
+ "newAcceptedAnnotations",
80
+ "selectedEntities",
81
+ "showActionError",
82
+ ]),
83
+ annotationText() {
84
+ if (this.isAnnotationBeingEdited) {
85
+ if (this.selectedEntities && this.selectedEntities.length > 0) {
86
+ return this.getTextFromEntities();
87
+ }
88
+ return this.$refs.contentEditable.textContent.trim();
89
+ } else {
90
+ return this.span.offset_string;
91
+ }
92
+ },
93
+ isAnnotationDeleted() {
94
+ return this.annotation.revised && !this.annotation.is_correct;
95
+ },
96
+ isAnnotationBeingEdited() {
97
+ return this.isAnnotationInEditMode(this.annotation.id, this.spanIndex);
98
+ },
99
+ },
100
+ watch: {
101
+ span(newValue) {
102
+ if (this.isAnnotationBeingEdited && newValue) {
103
+ if (this.isValueArray(newValue)) {
104
+ newValue.map((span) => {
105
+ if (
106
+ span.offset_string &&
107
+ span.offset_string !== this.span.offset_string
108
+ )
109
+ this.setText(span.offset_string);
110
+ });
111
+ } else {
112
+ if (
113
+ (newValue.offset_string &&
114
+ newValue.offset_string !== this.span.offset_string) ||
115
+ newValue.offset_string !==
116
+ this.$refs.contentEditable.textContent.trim()
117
+ )
118
+ this.setText(newValue.offset_string);
119
+ }
120
+ }
121
+ },
122
+ editAnnotation(newAnnotation, oldAnnotation) {
123
+ // verify if new annotation in edit mode is not this one and if this
124
+ // one was selected before so we set the state to the previous one (like a cancel)
125
+
126
+ if (
127
+ oldAnnotation &&
128
+ oldAnnotation.id === this.annotation.id &&
129
+ oldAnnotation.index === this.spanIndex
130
+ ) {
131
+ this.handleCancel(true);
132
+ }
133
+ },
134
+ selectedEntities(newValue) {
135
+ if (!newValue) return;
136
+
137
+ if (
138
+ this.editAnnotation &&
139
+ this.annotation.id === this.editAnnotation.id
140
+ ) {
141
+ this.setText(this.getTextFromEntities());
142
+ }
143
+ },
144
+ saveChanges(newValue) {
145
+ if (newValue) {
146
+ this.saveAnnotationChanges();
147
+ }
148
+ },
149
+ },
150
+ methods: {
151
+ setText(text) {
152
+ this.$refs.contentEditable.textContent = text;
153
+ },
154
+ handleEditAnnotation(event) {
155
+ if (this.publicView) return;
156
+
157
+ if (event) {
158
+ event.preventDefault();
159
+ }
160
+
161
+ if (
162
+ !this.publicView &&
163
+ !this.isAnnotationBeingEdited &&
164
+ !this.isLoading
165
+ ) {
166
+ this.$store.dispatch("selection/selectElement", this.annotation.id);
167
+ this.$store
168
+ .dispatch("document/setEditAnnotation", {
169
+ id: this.annotation.id,
170
+ index: this.spanIndex,
171
+ label: this.label.id,
172
+ labelSet: this.annotationSet.label_set.id,
173
+ annotationSet: this.annotationSet.id,
174
+ })
175
+ .then(() => {
176
+ this.$refs.contentEditable.focus();
177
+ })
178
+ .catch((error) => {
179
+ console.log(error);
180
+ });
181
+
182
+ const page = this.pageAtIndex(this.span.page_index);
183
+ if (page) {
184
+ const { x, y, width, height } = this.bboxToRect(page, this.span);
185
+
186
+ const selection = {
187
+ start: {
188
+ x,
189
+ y,
190
+ },
191
+ end: {
192
+ x: x + width,
193
+ y: y + height,
194
+ },
195
+ pageNumber: page.number,
196
+ custom: false,
197
+ };
198
+
199
+ this.$store.dispatch("selection/setSelection", {
200
+ selection,
201
+ span: this.span,
202
+ });
203
+ }
204
+ }
205
+ },
206
+ handleCancel(wasOutsideClick = false) {
207
+ if (wasOutsideClick) {
208
+ this.setText(this.span.offset_string);
209
+ } else {
210
+ this.$store.dispatch("selection/disableSelection");
211
+ this.$store.dispatch("document/endLoading");
212
+ }
213
+
214
+ this.isLoading = false;
215
+ if (this.$refs.contentEditable) {
216
+ this.$refs.contentEditable.blur();
217
+ }
218
+
219
+ this.$store.dispatch("document/setSelectedEntities", null);
220
+ },
221
+ handlePaste(event) {
222
+ // TODO: modify to only paste plain text
223
+ event.preventDefault();
224
+ },
225
+ saveAnnotationChanges(event) {
226
+ if (this.publicView) return;
227
+
228
+ if (event) {
229
+ event.preventDefault();
230
+ }
231
+
232
+ // API call handled in parent component - AnnotationRow
233
+ this.$emit(
234
+ "save-annotation-changes",
235
+ this.annotation,
236
+ this.spanIndex,
237
+ this.span,
238
+ this.annotationText
239
+ );
240
+ },
241
+ },
242
+ };
243
+ </script>
244
+
245
+ <style
246
+ scoped
247
+ lang="scss"
248
+ src="../../assets/scss/document_annotations.scss"
249
+ ></style>