@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,118 @@
1
+ <template>
2
+ <div class="edit-sidebar">
3
+ <div class="sidebar-header">
4
+ <h3 class="sidebar-title">
5
+ {{ $t("edit_document") }}
6
+ </h3>
7
+ <p class="description">
8
+ {{ $t("edit_early_access") }}
9
+ </p>
10
+ <p class="description">
11
+ {{ $t("select_pages") }}
12
+ </p>
13
+ </div>
14
+
15
+ <div class="buttons-container">
16
+ <div class="rotate-selected rotate">
17
+ <p :class="['pages-selected', buttonDisabled && 'disabled']">
18
+ {{ selectedPages.length }} {{ $t("selected") }}
19
+ </p>
20
+ <b-button
21
+ class="rotate-button"
22
+ :disabled="buttonDisabled"
23
+ @click="rotateLeft"
24
+ >
25
+ <div class="button-content">
26
+ <b-icon
27
+ icon="arrow-rotate-left"
28
+ class="is-small"
29
+ />
30
+ <span class="button-text">{{ $t("rotate_selected") }}</span>
31
+ </div>
32
+ </b-button>
33
+ <b-button
34
+ class="rotate-button"
35
+ :disabled="buttonDisabled"
36
+ @click="rotateRight"
37
+ >
38
+ <div class="button-content">
39
+ <b-icon
40
+ icon="arrow-rotate-right"
41
+ class="is-small"
42
+ />
43
+ <span class="button-text">{{ $t("rotate_selected") }}</span>
44
+ </div>
45
+ </b-button>
46
+ </div>
47
+
48
+ <div class="rotate-all rotate">
49
+ <b-button
50
+ class="rotate-button"
51
+ @click="rotateAllLeft"
52
+ >
53
+ <b-icon
54
+ icon="arrow-rotate-left"
55
+ class="is-small"
56
+ />
57
+ <span class="button-text">{{ $t("rotate_all") }}</span>
58
+ </b-button>
59
+ <b-button
60
+ class="rotate-button"
61
+ @click="rotateAllRight"
62
+ >
63
+ <b-icon
64
+ icon="arrow-rotate-right"
65
+ class="is-small"
66
+ />
67
+ <span class="button-text">{{ $t("rotate_all") }}</span>
68
+ </b-button>
69
+ </div>
70
+ </div>
71
+ </div>
72
+ </template>
73
+
74
+ <script>
75
+ /**
76
+ * This component renders buttons to rotate single pages or all pages
77
+ * in edit mode
78
+ * */
79
+
80
+ import { mapState } from "vuex";
81
+
82
+ export default {
83
+ name: "EditSidebar",
84
+ data() {
85
+ return {
86
+ buttonDisabled: true
87
+ };
88
+ },
89
+ computed: {
90
+ ...mapState("edit", ["selectedPages"])
91
+ },
92
+ watch: {
93
+ selectedPages(newValue) {
94
+ if (newValue.length > 0) {
95
+ this.buttonDisabled = false;
96
+ } else {
97
+ this.buttonDisabled = true;
98
+ }
99
+ }
100
+ },
101
+ methods: {
102
+ rotateLeft() {
103
+ this.$emit("rotate-left", "left");
104
+ },
105
+ rotateRight() {
106
+ this.$emit("rotate-right", "right");
107
+ },
108
+ rotateAllLeft() {
109
+ this.$emit("rotate-all-left");
110
+ },
111
+ rotateAllRight() {
112
+ this.$emit("rotate-all-right");
113
+ }
114
+ }
115
+ };
116
+ </script>
117
+
118
+ <style scoped lang="scss" src="../../assets/scss/document_edit.scss"></style>
@@ -0,0 +1,182 @@
1
+ <template>
2
+ <div class="split-overview">
3
+ <div class="back-section" @click="handleBackButton">
4
+ <div class="back-btn-section">
5
+ <b-icon
6
+ icon="arrow-left"
7
+ class="is-small arrow"
8
+ :style="{ color: '#858C9A', cursor: 'pointer' }"
9
+ />
10
+ </div>
11
+ <div class="back-text">
12
+ {{ $t("back_to_edit") }}
13
+ </div>
14
+ </div>
15
+ <div class="overview-title">
16
+ {{ $t("split_document") }}
17
+ </div>
18
+ <div class="new-documents-container">
19
+ <div
20
+ v-for="(page, index) in updatedDocument"
21
+ :key="index"
22
+ class="document-details"
23
+ >
24
+ <div class="overview-thumbnails">
25
+ <div class="split-documents">
26
+ <div
27
+ class="image-container"
28
+ @click="handlePageChange(page.pages[0].page_number)"
29
+ >
30
+ <div
31
+ :class="['thumbnail', page.pages.length > 1 && 'page-stack']"
32
+ >
33
+ <ServerImage
34
+ ref="image"
35
+ :style="{
36
+ transform:
37
+ 'rotate(' + getRotation(page.pages[0].id) + 'deg)',
38
+ }"
39
+ :image-url="getImageUrl(page)"
40
+ class="page-thumbnail"
41
+ />
42
+ <div class="icon-container">
43
+ <div class="action-icon">
44
+ <EyeIcon />
45
+ </div>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ </div>
51
+ <div class="doc-info">
52
+ <div class="file-name-section">
53
+ <input
54
+ type="text"
55
+ class="name-input"
56
+ :value="getFileName(page.name)"
57
+ @input="handleInput"
58
+ @paste="handlePaste"
59
+ @blur="handleChanges(page)"
60
+ />
61
+ <div class="file-extension-container">
62
+ <span>{{ `.${fileExtension}` }}</span>
63
+ </div>
64
+ </div>
65
+ <div class="category">
66
+ <DocumentCategory
67
+ :selected-document="selectedDocument"
68
+ :split-mode="splitMode"
69
+ :page="page"
70
+ :index="index"
71
+ @category-change="handleChanges"
72
+ />
73
+ </div>
74
+ </div>
75
+ </div>
76
+ </div>
77
+ </div>
78
+ </template>
79
+
80
+ <script>
81
+ /**
82
+ * This component will only be rendered if document pages were split
83
+ */
84
+
85
+ import { mapState } from "vuex";
86
+ import DocumentCategory from "../../components/DocumentCategory";
87
+ import ServerImage from "../../assets/images/ServerImage";
88
+ import EyeIcon from "../../assets/images/EyeIcon";
89
+
90
+ export default {
91
+ name: "SplitOverview",
92
+ components: {
93
+ DocumentCategory,
94
+ ServerImage,
95
+ EyeIcon,
96
+ },
97
+ props: {
98
+ fileName: {
99
+ type: String,
100
+ },
101
+ fileExtension: {
102
+ type: String,
103
+ },
104
+ },
105
+ data() {
106
+ return {
107
+ splitMode: true,
108
+ updatedFileName: null,
109
+ };
110
+ },
111
+ computed: {
112
+ ...mapState("document", ["selectedDocument", "pages"]),
113
+ ...mapState("edit", ["updatedDocument", "documentPagesListForEditMode"]),
114
+ },
115
+ methods: {
116
+ handleBackButton() {
117
+ this.$store.dispatch("edit/setSplitOverview", false);
118
+ },
119
+ handlePaste(event) {
120
+ // TODO: modify to only paste plain text
121
+ event.preventDefault();
122
+ },
123
+ handleInput(event) {
124
+ this.updatedFileName = event.target.value.trim();
125
+ },
126
+ handleChanges(page, category) {
127
+ // This function handles file name or category changes
128
+ const updatedPages = this.updatedDocument.map((splitPage) => {
129
+ if (splitPage.pages[0].id === page.pages[0].id) {
130
+ if (this.updatedFileName) {
131
+ return {
132
+ ...splitPage,
133
+ name: `${this.updatedFileName}.${this.fileExtension}`,
134
+ };
135
+ } else if (category) {
136
+ return {
137
+ ...splitPage,
138
+ category: category,
139
+ };
140
+ } else {
141
+ return splitPage;
142
+ }
143
+ }
144
+ return splitPage;
145
+ });
146
+
147
+ this.$store.dispatch("edit/setUpdatedDocument", updatedPages);
148
+
149
+ if (this.updatedFileName) {
150
+ this.updatedFileName = null;
151
+ }
152
+ },
153
+ handlePageChange(pageNumber) {
154
+ this.$emit("change-page", pageNumber);
155
+ },
156
+ getFileName(name) {
157
+ if (!name) return;
158
+
159
+ // Do not show file extension
160
+ return name.split(".").slice(0, -1).join(".");
161
+ },
162
+ getImageUrl(page) {
163
+ if (!this.documentPagesListForEditMode || !this.pages || !page) return;
164
+
165
+ // returns the first thumbnail in the pages array
166
+ // for each new document
167
+ const image = this.documentPagesListForEditMode.find(
168
+ (p) => p.page_number === page.pages[0].page_number
169
+ );
170
+
171
+ return `${image.thumbnail_url}?${image.updated_at}`;
172
+ },
173
+ getRotation(pageId) {
174
+ // rotate page
175
+ return this.documentPagesListForEditMode?.find((p) => p.id === pageId)
176
+ ?.angle;
177
+ },
178
+ },
179
+ };
180
+ </script>
181
+
182
+ <style scoped lang="scss" src="../../assets/scss/document_edit.scss"></style>
@@ -0,0 +1,4 @@
1
+ export { default as DocumentEdit } from "./DocumentEdit";
2
+ export { default as EditSidebar } from "./EditSidebar";
3
+ export { default as EditPages } from "./EditPages";
4
+ export { default as SplitOverview } from "./SplitOverview";
@@ -0,0 +1,53 @@
1
+ <template>
2
+ <section class="document-error-modal">
3
+ <b-modal v-model="isModalActive" :width="400">
4
+ <section class="modal-card-body">
5
+ <div class="header">
6
+ <div class="error-icon">
7
+ <ErrorIcon class="icon" />
8
+ </div>
9
+ <div class="btn-container" type="button" @click="closeModal">
10
+ <b-icon icon="xmark" class="close-btn" size="is-small" />
11
+ </div>
12
+ </div>
13
+ <div class="content">
14
+ <h3>{{ $t("document_error_title") }}</h3>
15
+ <p>{{ $t("document_error_info") }}</p>
16
+ </div>
17
+ </section>
18
+ <footer class="modal-card-foot">
19
+ <b-button type="is-primary" @click="handleContactSupport">
20
+ {{ $t("contact_support") }}
21
+ </b-button>
22
+ </footer>
23
+ </b-modal>
24
+ </section>
25
+ </template>
26
+
27
+ <script>
28
+ import { mapState } from "vuex";
29
+ import ErrorIcon from "../assets/images/ErrorIcon";
30
+
31
+ export default {
32
+ name: "DocumentError",
33
+ components: {
34
+ ErrorIcon,
35
+ },
36
+ data() {
37
+ return {
38
+ isModalActive: true,
39
+ };
40
+ },
41
+ methods: {
42
+ handleContactSupport() {
43
+ const documentError = "Document error";
44
+ this.$store.dispatch("document/contactSupport", documentError);
45
+ },
46
+ closeModal() {
47
+ this.$store.dispatch("document/setDocumentError", false);
48
+ },
49
+ },
50
+ };
51
+ </script>
52
+
53
+ <style scoped lang="scss" src="../assets/scss/document_error.scss"></style>
@@ -0,0 +1,48 @@
1
+ <template>
2
+ <div class="action-bar">
3
+ <div class="action-bar-elements">
4
+ <div v-if="documentActionBar.icon" class="action-icon">
5
+ <ActionIcon :icon="documentActionBar.icon" class="icon" />
6
+ </div>
7
+ <div v-if="documentActionBar.text" class="action-text">
8
+ {{ documentActionBar.text }}
9
+ </div>
10
+ <div v-if="documentActionBar.action" class="action-button">
11
+ <ActionButtons
12
+ :save-btn="documentActionBar.action !== null"
13
+ :is-loading="documentActionBar.loading"
14
+ :action-bar="true"
15
+ @save="handleSave()"
16
+ />
17
+ </div>
18
+ </div>
19
+ </div>
20
+ </template>
21
+
22
+ <script>
23
+ import { mapState } from "vuex";
24
+ import ActionButtons from "../DocumentAnnotations/ActionButtons";
25
+ import ActionIcon from "../../assets/images/ActionIcon";
26
+
27
+ export default {
28
+ name: "ActionBar",
29
+ components: {
30
+ ActionIcon,
31
+ ActionButtons,
32
+ },
33
+ computed: {
34
+ ...mapState("display", ["documentActionBar"]),
35
+ },
36
+ methods: {
37
+ handleSave() {
38
+ this.documentActionBar.action();
39
+ },
40
+ },
41
+ };
42
+ </script>
43
+
44
+ <style
45
+ scoped
46
+ lang="scss"
47
+ src="../../assets/scss/document_action_bar.scss"
48
+ ></style>
@@ -0,0 +1,149 @@
1
+ <template>
2
+ <v-group>
3
+ <v-rect
4
+ v-if="isSelectionValid"
5
+ ref="boxSelection"
6
+ :config="config"
7
+ :stroke-scale-enabled="false"
8
+ @dragend="onChange"
9
+ @transformend="onChange"
10
+ />
11
+ <v-transformer ref="boxTransformer" :config="transformerConfig" />
12
+ </v-group>
13
+ </template>
14
+
15
+ <script>
16
+ import { mapGetters, mapState, mapActions } from "vuex";
17
+
18
+ export default {
19
+ props: {
20
+ page: {
21
+ required: true,
22
+ type: Object,
23
+ },
24
+ },
25
+ computed: {
26
+ /**
27
+ * Konva options of the selection rectangle, based on the
28
+ * `selection` object.
29
+ */
30
+ config() {
31
+ return {
32
+ x: this.selection.start.x,
33
+ y: this.selection.start.y,
34
+ width: this.selection.end.x - this.selection.start.x,
35
+ height: this.selection.end.y - this.selection.start.y,
36
+ fill: this.isSelecting ? "#7B61FFB3" : "transparent",
37
+ stroke: this.isSelecting ? "transparent" : "#7B61FFB3",
38
+ strokeWidth: 1,
39
+ globalCompositeOperation: "multiply",
40
+ shadowForStrokeEnabled: false,
41
+ name: "boxSelection",
42
+ draggable: true,
43
+ };
44
+ },
45
+ transformerConfig() {
46
+ return {
47
+ borderEnabled: false,
48
+ rotateEnabled: false,
49
+ ignoreStroke: true,
50
+ keepRatio: false,
51
+ anchorStroke: "#7B61FF",
52
+ anchorSize: 6,
53
+ };
54
+ },
55
+ ...mapState("selection", ["selection", "isSelecting"]),
56
+ ...mapGetters("display", ["clientToBbox"]),
57
+ ...mapGetters("selection", ["isSelectionValid"]),
58
+ },
59
+ mounted() {
60
+ this.updateTransformer();
61
+
62
+ if (this.selection.custom) {
63
+ this.getBoxSelectionContent();
64
+ }
65
+ },
66
+ methods: {
67
+ updateTransformer() {
68
+ // here we need to manually attach or detach Transformer node
69
+ const transformer = this.$refs.boxTransformer;
70
+
71
+ // maybe we're out of sync and the transformer is not available, just return
72
+ if (!transformer) {
73
+ return;
74
+ }
75
+
76
+ const transformerNode = transformer.getNode();
77
+ const stage = transformerNode.getStage();
78
+ let selectedNode;
79
+ if (stage) {
80
+ selectedNode = stage.findOne(".boxSelection");
81
+ }
82
+
83
+ // do nothing if selected node is already attached
84
+ if (selectedNode === transformerNode.node()) {
85
+ return;
86
+ }
87
+
88
+ if (selectedNode) {
89
+ // attach to another node
90
+ transformerNode.nodes([selectedNode]);
91
+ } else {
92
+ // remove transformer
93
+ transformerNode.nodes([]);
94
+ }
95
+
96
+ transformerNode.getLayer().batchDraw();
97
+ },
98
+
99
+ getBoxSelectionContent() {
100
+ const box = this.clientToBbox(
101
+ this.page,
102
+ this.selection.start,
103
+ this.selection.end
104
+ );
105
+ this.$store.dispatch("selection/getTextFromBboxes", box);
106
+ },
107
+
108
+ /**
109
+ * This method is used for both transforms and drags since it just
110
+ * retrieves the rect's new attributes from the event and uses those
111
+ * to set the new selection state.
112
+ */
113
+ onChange(event) {
114
+ const { x, y, scaleX, scaleY, skewX, width, height } = event.target.attrs;
115
+ const realWidth = width * scaleX;
116
+ const realHeight = height * scaleY;
117
+ let start;
118
+ let end;
119
+
120
+ // we need to figure out if there's skewing going on, to fix start/end points
121
+ // (other cases appear to fix themselves automatically)
122
+ if (skewX >= 0) {
123
+ start = { x, y };
124
+ end = {
125
+ x: start.x + realWidth,
126
+ y: start.y + realHeight,
127
+ };
128
+ } else {
129
+ end = { x, y };
130
+ start = { x: end.x - realWidth, y: end.y - realHeight };
131
+ }
132
+
133
+ this.moveSelection({ start, end });
134
+
135
+ // reset node's everything after transform (we don't want to deal with that,
136
+ // just with regular x/y/width/height)
137
+ const node = this.$refs.boxSelection.getNode();
138
+ node.skewX(0);
139
+ node.skewY(0);
140
+ node.rotation(0);
141
+ node.scaleX(1);
142
+ node.scaleY(1);
143
+
144
+ this.getBoxSelectionContent();
145
+ },
146
+ ...mapActions("selection", ["moveSelection"]),
147
+ },
148
+ };
149
+ </script>