@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,159 @@
1
+ <template>
2
+ <div class="dashboard">
3
+ <DocumentTopBar />
4
+ <div :class="['dashboard-viewer', editMode ? 'edit-mode' : '']">
5
+ <DocumentThumbnails
6
+ v-if="!editMode"
7
+ ref="documentPages"
8
+ />
9
+ <ScrollingDocument
10
+ ref="scrollingDocument"
11
+ class="dashboard-document"
12
+ />
13
+ <DocumentAnnotations
14
+ v-if="!editMode"
15
+ ref="annotations"
16
+ />
17
+ <DocumentEdit
18
+ v-else
19
+ ref="editView"
20
+ />
21
+
22
+ <transition name="slide-fade">
23
+ <div
24
+ v-if="showActionError"
25
+ class="error-message"
26
+ :style="{ width: `${errorMessageWidth}px` }"
27
+ >
28
+ <ErrorMessage />
29
+ </div>
30
+ </transition>
31
+ </div>
32
+ <div
33
+ v-if="showDocumentError"
34
+ class="error-modal"
35
+ >
36
+ <DocumentError />
37
+ </div>
38
+ <div
39
+ v-if="!optimalResolution"
40
+ class="not-optimized"
41
+ >
42
+ <NotOptimizedViewportModal />
43
+ </div>
44
+ <div
45
+ v-if="!isMinimumWidth"
46
+ class="not-supported"
47
+ >
48
+ <div class="text">
49
+ {{ $t("resolution_not_supported") }}
50
+ </div>
51
+ </div>
52
+ </div>
53
+ </template>
54
+
55
+ <script>
56
+ import { mapGetters, mapState } from "vuex";
57
+ import { DocumentTopBar } from "./DocumentTopBar";
58
+ import { ScrollingDocument } from "./DocumentPage";
59
+ import { DocumentThumbnails } from "./DocumentThumbnails";
60
+ import { DocumentAnnotations } from "./DocumentAnnotations";
61
+ import { DocumentEdit } from "./DocumentEdit";
62
+ import ErrorMessage from "./ErrorMessage";
63
+ import NotOptimizedViewportModal from "./NotOptimizedViewportModal";
64
+ import DocumentError from "./DocumentError";
65
+
66
+ /**
67
+ * This component shows the PDF pages in a scrolling component and
68
+ * the annotations on the side.
69
+ */
70
+ export default {
71
+ name: "DocumentDashboard",
72
+ components: {
73
+ DocumentTopBar,
74
+ ScrollingDocument,
75
+ DocumentThumbnails,
76
+ DocumentAnnotations,
77
+ DocumentEdit,
78
+ ErrorMessage,
79
+ NotOptimizedViewportModal,
80
+ DocumentError
81
+ },
82
+ computed: {
83
+ ...mapState("display", [
84
+ "scale",
85
+ "fit",
86
+ "optimalResolution",
87
+ "pageWidthScale",
88
+ "currentPage"
89
+ ]),
90
+ ...mapState("document", [
91
+ "showActionError",
92
+ "showDocumentError",
93
+ "errorMessageWidth",
94
+ "selectedDocument"
95
+ ]),
96
+ ...mapState("edit", ["editMode"]),
97
+ ...mapGetters("display", ["isMinimumWidth"])
98
+ },
99
+ watch: {
100
+ selectedDocument(newDocument, oldDocument) {
101
+ if (newDocument && !oldDocument) {
102
+ // first time
103
+ this.resizeObserver.observe(this.$refs.scrollingDocument.$el);
104
+ } else if (newDocument) {
105
+ this.onDocumentResize();
106
+ }
107
+ }
108
+ },
109
+ mounted() {
110
+ this.resizeObserver = new ResizeObserver(this.onDocumentResize);
111
+ },
112
+ destroyed() {
113
+ if (this.$refs.scrollingDocument) {
114
+ this.resizeObserver.unobserve(this.$refs.scrollingDocument.$el);
115
+ }
116
+ },
117
+ data() {
118
+ return {
119
+ resizeObserver: null,
120
+ unwatchSelectedDocument: null
121
+ };
122
+ },
123
+ methods: {
124
+ elementsWidth() {
125
+ let elementsWidth = 1;
126
+ if (this.$refs.editView) {
127
+ elementsWidth += this.$refs.editView.$el.clientWidth;
128
+ }
129
+ if (this.$refs.documentPages) {
130
+ elementsWidth += this.$refs.documentPages.$el.clientWidth;
131
+ }
132
+ if (this.$refs.annotations) {
133
+ elementsWidth += this.$refs.annotations.$el.clientWidth;
134
+ }
135
+ return elementsWidth;
136
+ },
137
+ onDocumentResize() {
138
+ this.$store.dispatch(
139
+ "display/updateOptimalResolution",
140
+ this.$el.offsetWidth
141
+ );
142
+ if (this.selectedDocument.pages[0]) {
143
+ this.$store.dispatch("display/updateScale", {
144
+ elementsWidth: this.elementsWidth(),
145
+ client: {
146
+ width: this.$el.clientWidth,
147
+ height: this.$el.clientHeight
148
+ },
149
+ viewport: {
150
+ width: this.selectedDocument.pages[0].size[0],
151
+ height: this.selectedDocument.pages[0].size[1]
152
+ }
153
+ });
154
+ }
155
+ }
156
+ }
157
+ };
158
+ </script>
159
+ <style scoped lang="scss" src="../assets/scss/document_dashboard.scss"></style>
@@ -0,0 +1,279 @@
1
+ <template>
2
+ <div :class="['document-edit', splitOverview && 'split-overview-component']">
3
+ <div
4
+ v-if="!splitOverview"
5
+ class="pages-section"
6
+ >
7
+ <EditPages
8
+ :active-splitting-lines="activeSplittingLines"
9
+ @change-page="changePage"
10
+ @handle-splitting-lines="handleSplittingLines"
11
+ @check-move="checkMove"
12
+ @handle-drag-end="handleDragEnd"
13
+ />
14
+ </div>
15
+ <div
16
+ v-else
17
+ class="split-overview-section"
18
+ >
19
+ <SplitOverview
20
+ :file-name="fileName"
21
+ :file-extension="fileExtension"
22
+ @change-page="changePage"
23
+ />
24
+ </div>
25
+ <div
26
+ v-if="!splitOverview"
27
+ class="sidebar"
28
+ >
29
+ <EditSidebar
30
+ @rotate-left="rotatePage"
31
+ @rotate-right="rotatePage"
32
+ @rotate-all-left="handleRotationsToTheLeft"
33
+ @rotate-all-right="handleRotationsToTheRight"
34
+ />
35
+ </div>
36
+ </div>
37
+ </template>
38
+ <script>
39
+ import { mapState } from "vuex";
40
+ import EditSidebar from "./EditSidebar";
41
+ import SplitOverview from "./SplitOverview";
42
+ import EditPages from "./EditPages";
43
+
44
+ /**
45
+ * This component shows a document thumbnail grid view and sidebar, to be able to edit the document.
46
+ */
47
+ export default {
48
+ name: "DocumentEdit",
49
+ components: {
50
+ EditSidebar,
51
+ SplitOverview,
52
+ EditPages
53
+ },
54
+ data() {
55
+ return {
56
+ fileName: [],
57
+ fileExtension: null,
58
+ activeSplittingLines: [],
59
+ dragging: false,
60
+ prevPageAtIndex: null
61
+ };
62
+ },
63
+ computed: {
64
+ ...mapState("document", ["recalculatingAnnotations", "selectedDocument"]),
65
+ ...mapState("display", ["currentPage"]),
66
+ ...mapState("edit", [
67
+ "editMode",
68
+ "documentPagesListForEditMode",
69
+ "updatedDocument",
70
+ "splitOverview",
71
+ "selectedPages"
72
+ ])
73
+ },
74
+ watch: {
75
+ pages() {
76
+ if (!this.selectedDocument) return;
77
+ this.setPages();
78
+ },
79
+ splitOverview(newValue) {
80
+ if (newValue) {
81
+ this.splitFileNameFromExtension();
82
+ }
83
+ },
84
+ documentPagesListForEditMode(newValue) {
85
+ if (newValue) {
86
+ this.saveUpdatedDocument();
87
+ }
88
+ }
89
+ },
90
+ mounted() {
91
+ this.setPages();
92
+ },
93
+ methods: {
94
+ setPages() {
95
+ if (!this.selectedDocument) {
96
+ return;
97
+ }
98
+ // set array of pages only with the data we need
99
+ const pages = this.createDocumentPagesListForEditMode();
100
+ this.$store.dispatch("edit/setDocumentPagesListForEditMode", pages);
101
+ // create array to handle the splitting
102
+ // length - 1 because of how many lines to split we need (last one not necessary)
103
+ this.activeSplittingLines = new Array(
104
+ this.selectedDocument.pages.length - 1
105
+ );
106
+ },
107
+ createDocumentPagesListForEditMode() {
108
+ return this.selectedDocument.pages.map(page => {
109
+ return {
110
+ id: page.id,
111
+ angle: 0,
112
+ page_number: page.number,
113
+ thumbnail_url: page.thumbnail_url,
114
+ image_url: page.image_url,
115
+ size: page.size,
116
+ updated_at: this.selectedDocument.downloaded_at
117
+ };
118
+ });
119
+ },
120
+ changePage(pageNumber) {
121
+ // This will scroll to the clicked page
122
+ if (pageNumber != this.currentPage) {
123
+ this.$store.dispatch(
124
+ "display/updateCurrentPage",
125
+ parseInt(pageNumber, 10)
126
+ );
127
+ }
128
+ },
129
+
130
+ /** ROTATE */
131
+ rotatePage(direction) {
132
+ const page = this.selectedPages.map(page => {
133
+ return page;
134
+ });
135
+
136
+ this.$store.dispatch("edit/rotatePage", {
137
+ page,
138
+ direction
139
+ });
140
+ },
141
+ handleRotationsToTheLeft() {
142
+ this.$store.dispatch("edit/updateRotationToTheLeft");
143
+ },
144
+ handleRotationsToTheRight() {
145
+ this.$store.dispatch("edit/updateRotationToTheRight");
146
+ },
147
+
148
+ /** SPLIT */
149
+ splitFileNameFromExtension() {
150
+ if (!this.selectedDocument) return;
151
+
152
+ // Save the file name and the extension in different variables
153
+ // to be used in the next step of the splitting
154
+
155
+ if (this.selectedDocument.data_file_name) {
156
+ this.fileName = this.selectedDocument.data_file_name
157
+ .split(".")
158
+ .slice(0, -1)
159
+ .join(".");
160
+ }
161
+
162
+ if (this.selectedDocument.data_file_name) {
163
+ this.fileExtension = this.selectedDocument.data_file_name
164
+ .split(".")
165
+ .at(-1);
166
+ }
167
+ },
168
+ handleSplittingLines(page) {
169
+ // For splitting line purposes
170
+ // Add page number to specific index
171
+ // Or replace it with 0 (to keep the same index) if it exists
172
+ const found = this.activeSplittingLines.find(
173
+ item => item === page.page_number
174
+ );
175
+
176
+ if (found) {
177
+ this.activeSplittingLines.splice(page.page_number - 1, 1, 0);
178
+ } else {
179
+ this.activeSplittingLines.splice(
180
+ page.page_number - 1,
181
+ 1,
182
+ page.page_number
183
+ );
184
+ }
185
+
186
+ this.saveUpdatedDocument();
187
+ },
188
+ saveUpdatedDocument() {
189
+ this.splitFileNameFromExtension();
190
+
191
+ // Check how many sub docs we have
192
+ const subDocuments = this.activeSplittingLines.filter(item => item !== 0);
193
+
194
+ // Create array of objects
195
+ // with a fixed size based on how many sub documents are currently
196
+ const pageObjectArray = new Array(subDocuments.length + 1);
197
+
198
+ // Loop over the created array
199
+ // for each iteration we create the page object with the correponding data
200
+ for (let i = 0; i < pageObjectArray.length; i++) {
201
+ const pageObject = {
202
+ name: this.handleFileName(i),
203
+ category: this.selectedDocument.category,
204
+ pages: this.handleSubPages(i, subDocuments)
205
+ };
206
+
207
+ // Then we replace the "undefined" with the created object
208
+ pageObjectArray.splice(i, 1, pageObject);
209
+ }
210
+
211
+ // Set the state to the created array
212
+ this.$store.dispatch("edit/setUpdatedDocument", pageObjectArray);
213
+ },
214
+ handleFileName(index) {
215
+ let newFileName;
216
+
217
+ // Return original file name,
218
+ // file name + copy,
219
+ // or file name + copy + number
220
+ // based on where the object will be located in the array
221
+ if (index === 0) {
222
+ newFileName = this.selectedDocument.data_file_name;
223
+ } else if (index === 1) {
224
+ newFileName = `${this.fileName}_copy.${this.fileExtension}`;
225
+ } else {
226
+ newFileName = `${this.fileName}_copy${index}.${this.fileExtension}`;
227
+ }
228
+ return newFileName;
229
+ },
230
+ handleSubPages(index, splittingLine) {
231
+ // assign the correct pages to each object
232
+ let pages;
233
+
234
+ if (index === 0) {
235
+ pages = this.documentPagesListForEditMode.slice(
236
+ 0,
237
+ splittingLine[index]
238
+ );
239
+ } else {
240
+ if (!splittingLine[index]) {
241
+ pages = this.documentPagesListForEditMode.slice(
242
+ splittingLine[index - 1]
243
+ );
244
+ } else {
245
+ pages = this.documentPagesListForEditMode.slice(
246
+ splittingLine[index - 1],
247
+ splittingLine[index]
248
+ );
249
+ }
250
+ }
251
+ return pages;
252
+ },
253
+
254
+ /** SORT */
255
+ checkMove(e) {
256
+ // Save the page placed originally where the page we are dragging will go
257
+ this.prevPageAtIndex = this.documentPagesListForEditMode.find(
258
+ page =>
259
+ this.documentPagesListForEditMode.indexOf(page) ===
260
+ e.draggedContext.futureIndex
261
+ );
262
+ },
263
+ handleDragEnd() {
264
+ // Update page numbers
265
+ const pages = this.documentPagesListForEditMode.map(page => {
266
+ const index = this.documentPagesListForEditMode.indexOf(page);
267
+ return {
268
+ ...page,
269
+ page_number: index + 1
270
+ };
271
+ });
272
+
273
+ this.$store.dispatch("edit/setDocumentPagesListForEditMode", pages);
274
+ }
275
+ }
276
+ };
277
+ </script>
278
+
279
+ <style scoped lang="scss" src="../../assets/scss/document_edit.scss"></style>
@@ -0,0 +1,213 @@
1
+ <template>
2
+ <div class="edit-pages">
3
+ <draggable
4
+ v-model="editPages"
5
+ class="document-grid"
6
+ easing="cubic-bezier(0.37, 0, 0.63, 1)"
7
+ @start="dragging = true"
8
+ @end="handleDragEnd"
9
+ @move="checkMove"
10
+ >
11
+ <div
12
+ v-for="(page, index) in editPages"
13
+ :key="page.id"
14
+ class="image-section"
15
+ tabindex="0"
16
+ @focusout="clickOutside"
17
+ >
18
+ <div
19
+ class="image-container"
20
+ :tabindex="index"
21
+ @click="selectPage(page)"
22
+ >
23
+ <div class="thumbnail">
24
+ <div
25
+ :class="[
26
+ 'img-container',
27
+ selected && isPageSelected(page.id) === page.id && 'selected',
28
+ ]"
29
+ >
30
+ <ServerImage
31
+ class="img-thumbnail"
32
+ :image-url="`${page.thumbnail_url}?${page.updated_at}`"
33
+ :style="{
34
+ transform: 'rotate(' + getRotation(page.id) + 'deg)',
35
+ }"
36
+ >
37
+ <b-skeleton
38
+ width="57px"
39
+ height="57px"
40
+ />
41
+ </ServerImage>
42
+ </div>
43
+ <div class="icon-container">
44
+ <div class="action-icon">
45
+ <EyeIcon />
46
+ </div>
47
+ </div>
48
+ </div>
49
+ <span class="page-number">{{ page.page_number }}</span>
50
+ </div>
51
+ <div
52
+ :class="[
53
+ 'splitting-lines',
54
+ activeSplittingLines &&
55
+ activeSplittingLines[index] === page.page_number &&
56
+ 'active-split',
57
+ ]"
58
+ @click="handleSplittingLines(page)"
59
+ >
60
+ <div class="scissors-icon">
61
+ <b-icon
62
+ icon="scissors"
63
+ class="is-small"
64
+ />
65
+ </div>
66
+ <div
67
+ v-if="
68
+ activeSplittingLines &&
69
+ activeSplittingLines[index] === page.page_number
70
+ "
71
+ class="lines"
72
+ >
73
+ <SplitZigZag />
74
+ </div>
75
+ <div
76
+ v-else
77
+ class="lines"
78
+ >
79
+ <SplitLines />
80
+ </div>
81
+ </div>
82
+ </div>
83
+ </draggable>
84
+ </div>
85
+ </template>
86
+
87
+ <script>
88
+ /**
89
+ * This component renders a grid of the document pages
90
+ * that will be possible to resort, split and/or rotate
91
+ */
92
+
93
+ import { mapState } from "vuex";
94
+ import ServerImage from "../../assets/images/ServerImage";
95
+ import SplitLines from "../../assets/images/SplitLines";
96
+ import SplitZigZag from "../../assets/images/SplitZigZag";
97
+ import EyeIcon from "../../assets/images/EyeIcon";
98
+ import draggable from "vuedraggable";
99
+
100
+ export default {
101
+ name: "EditPages",
102
+ components: {
103
+ ServerImage,
104
+ SplitLines,
105
+ SplitZigZag,
106
+ EyeIcon,
107
+ draggable,
108
+ },
109
+ props: {
110
+ activeSplittingLines: {
111
+ type: Array,
112
+ },
113
+ },
114
+ data() {
115
+ return {
116
+ editPages: null,
117
+ selected: null,
118
+ };
119
+ },
120
+ computed: {
121
+ ...mapState("document", [
122
+ "pages",
123
+ "recalculatingAnnotations",
124
+ "selectedDocument",
125
+ ]),
126
+ ...mapState("edit", [
127
+ "editMode",
128
+ "documentPagesListForEditMode",
129
+ "splitOverview",
130
+ "selectedPages",
131
+ "splitOverview",
132
+ ]),
133
+ },
134
+ watch: {
135
+ documentPagesListForEditMode(newValue, oldValue) {
136
+ if (newValue !== oldValue) {
137
+ this.editPages = newValue;
138
+ }
139
+ },
140
+ editPages(newValue, oldValue) {
141
+ if (newValue !== oldValue) {
142
+ this.$store.dispatch("edit/setDocumentPagesListForEditMode", newValue);
143
+ }
144
+ },
145
+ splitOverview(newValue) {
146
+ if (newValue) {
147
+ this.editPages = this.documentPagesListForEditMode;
148
+ }
149
+ },
150
+ },
151
+ mounted() {
152
+ this.editPages = this.documentPagesListForEditMode;
153
+ },
154
+ methods: {
155
+ handlePageChange(pageNumber) {
156
+ this.$emit("change-page", pageNumber);
157
+ },
158
+ isPageSelected(id) {
159
+ if (this.selectedPages.length === 0) return;
160
+ const selectedPage = this.selectedPages.find((page) => page.id === id);
161
+ if (selectedPage) return selectedPage.id;
162
+ },
163
+ selectPage(page) {
164
+ if (!page) return;
165
+ this.$emit("change-page", page.page_number);
166
+ const selectedPage = {
167
+ id: page.id,
168
+ number: page.page_number,
169
+ thumbnail_url: page.thumbnail_url,
170
+ };
171
+ this.selected = true;
172
+
173
+ this.$store.dispatch("edit/setSelectedPages", selectedPage);
174
+ },
175
+ clickOutside(event) {
176
+ if (!event || this.selectedPages.length === 0) return;
177
+
178
+ // Check if user clicks in any element other than thumbnail or buttons to deselect the thumbnail
179
+ if (
180
+ event.target.className.includes("button") ||
181
+ event.target.className.includes("image-container") ||
182
+ event.target.className.includes("icon")
183
+ ) {
184
+ return;
185
+ }
186
+
187
+ this.deselect();
188
+ },
189
+ deselect() {
190
+ this.selected = null;
191
+ this.$store.dispatch("edit/setSelectedPages");
192
+ },
193
+ getRotation(pageId) {
194
+ // rotate page
195
+ return this.documentPagesListForEditMode?.find((p) => p.id === pageId)
196
+ ?.angle;
197
+ },
198
+ handleSplittingLines(page) {
199
+ this.$emit("handle-splitting-lines", page);
200
+ },
201
+ checkMove(event) {
202
+ this.$emit("check-move", event);
203
+ },
204
+ handleDragEnd() {
205
+ this.draggable = false;
206
+
207
+ this.$emit("handle-drag-end");
208
+ },
209
+ },
210
+ };
211
+ </script>
212
+
213
+ <style scoped lang="scss" src="../../assets/scss/document_edit.scss"></style>