@konfuzio/document-validation-ui 0.1.19-dev.1 → 0.1.19

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 (145) hide show
  1. package/.eslintrc.js +10 -10
  2. package/.prettierrc.json +1 -1
  3. package/LICENSE +21 -21
  4. package/README.md +24 -24
  5. package/cypress.config.js +13 -13
  6. package/dist/css/app.css +1 -1
  7. package/dist/index.html +1 -1
  8. package/dist/js/app.js +1 -1
  9. package/dist/js/app.js.map +1 -1
  10. package/dist/js/chunk-vendors.js +1 -1
  11. package/dist/js/chunk-vendors.js.map +1 -1
  12. package/jest.config.js +4 -4
  13. package/package.json +66 -66
  14. package/src/api.js +82 -82
  15. package/src/assets/images/AcceptedCheckMark.vue +8 -8
  16. package/src/assets/images/AcceptedUser.vue +8 -8
  17. package/src/assets/images/ActionIcon.vue +60 -60
  18. package/src/assets/images/ArrowDownKey.vue +11 -11
  19. package/src/assets/images/ArrowUpKey.vue +11 -11
  20. package/src/assets/images/CategoryIconImg.vue +13 -13
  21. package/src/assets/images/CheckMark.vue +8 -8
  22. package/src/assets/images/DraggableIcon.vue +14 -14
  23. package/src/assets/images/EditDocIcon.vue +12 -12
  24. package/src/assets/images/EmptyStateImg.vue +129 -129
  25. package/src/assets/images/ErrorIcon.vue +28 -28
  26. package/src/assets/images/EyeIcon.vue +11 -11
  27. package/src/assets/images/FileNameNotSavedImage.vue +26 -26
  28. package/src/assets/images/FileNameSavedImage.vue +14 -14
  29. package/src/assets/images/FitZoomIcon.vue +16 -16
  30. package/src/assets/images/GridIcon.vue +16 -16
  31. package/src/assets/images/KeyboardIcon.vue +16 -16
  32. package/src/assets/images/MagicWandIcon.vue +16 -16
  33. package/src/assets/images/MinusIcon.vue +13 -13
  34. package/src/assets/images/NotFoundIcon.vue +16 -16
  35. package/src/assets/images/NotOptimizedIllustration.vue +651 -651
  36. package/src/assets/images/PlusIcon.vue +13 -13
  37. package/src/assets/images/QuestionMark.vue +12 -12
  38. package/src/assets/images/ServerImage.vue +73 -73
  39. package/src/assets/images/SettingsIcon.vue +14 -14
  40. package/src/assets/images/SplitLines.vue +18 -18
  41. package/src/assets/images/SplitZigZag.vue +49 -49
  42. package/src/assets/images/StarIcon.vue +16 -16
  43. package/src/assets/images/StatusImg.vue +14 -14
  44. package/src/assets/images/TranslateArrows.vue +33 -33
  45. package/src/assets/scss/ann_set_table_options.scss +26 -26
  46. package/src/assets/scss/annotation_details.scss +141 -141
  47. package/src/assets/scss/choose_label_set_modal.scss +65 -65
  48. package/src/assets/scss/document_action_bar.scss +37 -37
  49. package/src/assets/scss/document_annotations.scss +558 -537
  50. package/src/assets/scss/document_category.scss +85 -85
  51. package/src/assets/scss/document_dashboard.scss +52 -52
  52. package/src/assets/scss/document_edit.scss +410 -410
  53. package/src/assets/scss/document_error.scss +81 -81
  54. package/src/assets/scss/document_name.scss +60 -60
  55. package/src/assets/scss/document_page.scss +12 -12
  56. package/src/assets/scss/document_thumbnails.scss +41 -41
  57. package/src/assets/scss/document_toolbar.scss +111 -111
  58. package/src/assets/scss/document_top_bar.scss +171 -171
  59. package/src/assets/scss/document_viewport_modal.scss +25 -25
  60. package/src/assets/scss/documents_list.scss +141 -141
  61. package/src/assets/scss/edit_page_thumbnail.scss +53 -53
  62. package/src/assets/scss/empty_state.scss +34 -34
  63. package/src/assets/scss/extracting_data.scss +35 -35
  64. package/src/assets/scss/imports.scss +1 -1
  65. package/src/assets/scss/multi_ann_table_overlay.scss +38 -38
  66. package/src/assets/scss/multi_ann_table_popup.scss +12 -12
  67. package/src/assets/scss/new_annotation.scss +102 -102
  68. package/src/assets/scss/scrolling_document.scss +19 -19
  69. package/src/assets/scss/theme.scss +801 -801
  70. package/src/assets/scss/variables.scss +66 -66
  71. package/src/components/App.cy.js +7 -7
  72. package/src/components/App.vue +187 -187
  73. package/src/components/DocumentAnnotations/AnnotationActionButtons.vue +152 -168
  74. package/src/components/DocumentAnnotations/AnnotationContent.vue +210 -210
  75. package/src/components/DocumentAnnotations/AnnotationDetails.vue +251 -251
  76. package/src/components/DocumentAnnotations/AnnotationRow.vue +752 -752
  77. package/src/components/DocumentAnnotations/AnnotationSetActionButtons.vue +89 -89
  78. package/src/components/DocumentAnnotations/ChooseLabelSetModal.vue +186 -186
  79. package/src/components/DocumentAnnotations/DocumentAnnotations.cy.js +441 -441
  80. package/src/components/DocumentAnnotations/DocumentAnnotations.vue +534 -534
  81. package/src/components/DocumentAnnotations/DocumentLabel.vue +189 -189
  82. package/src/components/DocumentAnnotations/EmptyAnnotation.vue +193 -193
  83. package/src/components/DocumentAnnotations/EmptyState.vue +21 -21
  84. package/src/components/DocumentAnnotations/ExtractingData.vue +41 -41
  85. package/src/components/DocumentAnnotations/LoadingAnnotations.vue +43 -43
  86. package/src/components/DocumentAnnotations/LoadingLabels.vue +43 -43
  87. package/src/components/DocumentAnnotations/MultiAnnotationTableOverlay.vue +338 -338
  88. package/src/components/DocumentAnnotations/index.js +8 -8
  89. package/src/components/DocumentCategory.vue +281 -281
  90. package/src/components/DocumentDashboard.vue +170 -170
  91. package/src/components/DocumentEdit/DocumentEdit.cy.js +541 -541
  92. package/src/components/DocumentEdit/DocumentEdit.vue +503 -503
  93. package/src/components/DocumentEdit/EditConfirmationModal.vue +55 -55
  94. package/src/components/DocumentEdit/EditPageThumbnail.vue +114 -114
  95. package/src/components/DocumentEdit/EditPages.vue +161 -161
  96. package/src/components/DocumentEdit/EditSidebar.vue +154 -154
  97. package/src/components/DocumentEdit/RenameAndCategorize.vue +184 -184
  98. package/src/components/DocumentEdit/SidebarButtons.vue +53 -53
  99. package/src/components/DocumentEdit/SplitInfoBar.vue +21 -21
  100. package/src/components/DocumentEdit/index.js +4 -4
  101. package/src/components/DocumentModals/DocumentErrorModal.vue +58 -58
  102. package/src/components/DocumentModals/NotOptimizedViewportModal.vue +51 -51
  103. package/src/components/DocumentPage/ActionBar.vue +48 -48
  104. package/src/components/DocumentPage/AnnSetTableOptions.vue +111 -111
  105. package/src/components/DocumentPage/BoxSelection.vue +152 -152
  106. package/src/components/DocumentPage/DocumentPage.cy.js +92 -92
  107. package/src/components/DocumentPage/DocumentPage.vue +568 -568
  108. package/src/components/DocumentPage/DocumentToolbar.cy.js +215 -215
  109. package/src/components/DocumentPage/DocumentToolbar.vue +228 -228
  110. package/src/components/DocumentPage/DummyPage.vue +55 -55
  111. package/src/components/DocumentPage/MultiAnnSelection.vue +371 -371
  112. package/src/components/DocumentPage/NewAnnotation.vue +308 -308
  113. package/src/components/DocumentPage/ScrollingDocument.vue +149 -149
  114. package/src/components/DocumentPage/ScrollingPage.vue +179 -179
  115. package/src/components/DocumentPage/index.js +5 -5
  116. package/src/components/DocumentThumbnails/DocumentThumbnails.cy.js +67 -67
  117. package/src/components/DocumentThumbnails/DocumentThumbnails.vue +132 -132
  118. package/src/components/DocumentThumbnails/LoadingThumbnail.vue +25 -25
  119. package/src/components/DocumentThumbnails/index.js +1 -1
  120. package/src/components/DocumentTopBar/DocumentName.vue +236 -236
  121. package/src/components/DocumentTopBar/DocumentTopBar.cy.js +222 -222
  122. package/src/components/DocumentTopBar/DocumentTopBar.vue +202 -202
  123. package/src/components/DocumentTopBar/DocumentTopBarButtons.vue +183 -183
  124. package/src/components/DocumentTopBar/KeyboardActionsDescription.vue +74 -74
  125. package/src/components/DocumentTopBar/index.js +3 -3
  126. package/src/components/DocumentsList/DocumentsList.vue +121 -121
  127. package/src/components/DocumentsList/index.js +1 -1
  128. package/src/components/ErrorMessage.vue +40 -40
  129. package/src/components/index.js +1 -1
  130. package/src/constants.js +5 -5
  131. package/src/directives/scroll.js +28 -28
  132. package/src/i18n.js +22 -22
  133. package/src/icons.js +45 -45
  134. package/src/locales/de.json +148 -148
  135. package/src/locales/en.json +148 -148
  136. package/src/main.js +26 -26
  137. package/src/store/category.js +191 -191
  138. package/src/store/display.js +311 -311
  139. package/src/store/document.js +1438 -1438
  140. package/src/store/edit.js +316 -316
  141. package/src/store/index.js +21 -21
  142. package/src/store/project.js +143 -143
  143. package/src/store/selection.js +210 -210
  144. package/src/utils/utils.js +54 -54
  145. package/vue.config.js +25 -25
@@ -1,149 +1,149 @@
1
- <template>
2
- <div id="scrolling-document">
3
- <div
4
- ref="scrollingDocument"
5
- v-scroll.immediate="updateScrollBounds"
6
- class="scrolling-document"
7
- >
8
- <div
9
- v-if="
10
- selectedDocument && scale && !loading && !recalculatingAnnotations
11
- "
12
- >
13
- <ScrollingPage
14
- v-for="page in editMode ? pagesForPostprocess : pages"
15
- :key="page.number"
16
- ref="scrollingPage"
17
- :page="page"
18
- :client-height="clientHeight"
19
- :scroll-top="scrollTop"
20
- class="scrolling-page"
21
- @page-jump="onPageJump"
22
- />
23
- </div>
24
-
25
- <div v-else class="loading-page">
26
- <b-skeleton width="100%" height="1000px" />
27
- </div>
28
- </div>
29
- <Toolbar v-if="showToolbar" />
30
- <ActionBar v-if="showActionBar" />
31
- </div>
32
- </template>
33
- <script>
34
- import { mapState, mapGetters } from "vuex";
35
- import scroll from "../../directives/scroll";
36
- import ScrollingPage from "./ScrollingPage";
37
- import Toolbar from "./DocumentToolbar";
38
- import ActionBar from "./ActionBar";
39
-
40
- export default {
41
- components: {
42
- ScrollingPage,
43
- Toolbar,
44
- ActionBar,
45
- },
46
- directives: {
47
- scroll,
48
- },
49
-
50
- data() {
51
- return {
52
- scrollTop: 0,
53
- clientHeight: 0,
54
- isScolling: false,
55
- scrollTimeout: null,
56
- };
57
- },
58
-
59
- computed: {
60
- ...mapState("document", [
61
- "recalculatingAnnotations",
62
- "selectedDocument",
63
- "loading",
64
- "annotationSets",
65
- ]),
66
- ...mapState("edit", [
67
- "editMode",
68
- "documentPagesListForEditMode",
69
- "pagesForPostprocess",
70
- ]),
71
- ...mapState("display", [
72
- "scale",
73
- "documentActionBar",
74
- "pageChangedFromThumbnail",
75
- "currentPage",
76
- ]),
77
- ...mapGetters("display", ["visiblePageRange"]),
78
-
79
- pages() {
80
- if (this.selectedDocument) {
81
- return this.selectedDocument.pages;
82
- } else {
83
- return [];
84
- }
85
- },
86
- showToolbar() {
87
- return (
88
- !this.loading &&
89
- this.pages.length > 0 &&
90
- this.scale &&
91
- !this.documentActionBar
92
- );
93
- },
94
- showActionBar() {
95
- return this.documentActionBar !== null;
96
- },
97
- },
98
- watch: {
99
- loading() {
100
- this.scrollTop = 0;
101
- },
102
- },
103
- mounted() {
104
- this.$refs.scrollingDocument.addEventListener("scroll", this.handleScroll);
105
- },
106
-
107
- methods: {
108
- updateScrollBounds() {
109
- const { scrollTop, clientHeight } = this.$refs.scrollingDocument;
110
- this.scrollTop = scrollTop;
111
- this.clientHeight = clientHeight;
112
- },
113
- /**
114
- * Scrolls the ScrollingDocument to the offset specified by scrollTop & scrollLeft (if zoomed in)
115
- * (i.e., another page).
116
- */
117
- onPageJump(scrollTop, scrollLeft) {
118
- const scrollY = scrollTop - (this.$refs.scrollingDocument.offsetTop + 4); // + 4 due to margin between pages
119
- const scrollX = scrollLeft - this.$refs.scrollingDocument.offsetLeft - 4; // - 4 to add more space before the entity
120
-
121
- this.$refs.scrollingDocument.scroll(scrollX, scrollY);
122
- },
123
- handleScroll() {
124
- if (this.pages.length === 1) return;
125
-
126
- this.isScrolling = true;
127
-
128
- clearTimeout(this.scrollTimeout);
129
-
130
- this.scrollTimeout = setTimeout(() => {
131
- this.isScrolling = false;
132
-
133
- if (
134
- this.pageChangedFromThumbnail &&
135
- this.visiblePageRange[1] === this.currentPage
136
- ) {
137
- this.$store.dispatch("display/setPageChangedFromThumbnail", false);
138
- }
139
- }, 300);
140
- },
141
- },
142
- };
143
- </script>
144
-
145
- <style
146
- scoped
147
- lang="scss"
148
- src="../../assets/scss/scrolling_document.scss"
149
- ></style>
1
+ <template>
2
+ <div id="scrolling-document">
3
+ <div
4
+ ref="scrollingDocument"
5
+ v-scroll.immediate="updateScrollBounds"
6
+ class="scrolling-document"
7
+ >
8
+ <div
9
+ v-if="
10
+ selectedDocument && scale && !loading && !recalculatingAnnotations
11
+ "
12
+ >
13
+ <ScrollingPage
14
+ v-for="page in editMode ? pagesForPostprocess : pages"
15
+ :key="page.number"
16
+ ref="scrollingPage"
17
+ :page="page"
18
+ :client-height="clientHeight"
19
+ :scroll-top="scrollTop"
20
+ class="scrolling-page"
21
+ @page-jump="onPageJump"
22
+ />
23
+ </div>
24
+
25
+ <div v-else class="loading-page">
26
+ <b-skeleton width="100%" height="1000px" />
27
+ </div>
28
+ </div>
29
+ <Toolbar v-if="showToolbar" />
30
+ <ActionBar v-if="showActionBar" />
31
+ </div>
32
+ </template>
33
+ <script>
34
+ import { mapState, mapGetters } from "vuex";
35
+ import scroll from "../../directives/scroll";
36
+ import ScrollingPage from "./ScrollingPage";
37
+ import Toolbar from "./DocumentToolbar";
38
+ import ActionBar from "./ActionBar";
39
+
40
+ export default {
41
+ components: {
42
+ ScrollingPage,
43
+ Toolbar,
44
+ ActionBar,
45
+ },
46
+ directives: {
47
+ scroll,
48
+ },
49
+
50
+ data() {
51
+ return {
52
+ scrollTop: 0,
53
+ clientHeight: 0,
54
+ isScolling: false,
55
+ scrollTimeout: null,
56
+ };
57
+ },
58
+
59
+ computed: {
60
+ ...mapState("document", [
61
+ "recalculatingAnnotations",
62
+ "selectedDocument",
63
+ "loading",
64
+ "annotationSets",
65
+ ]),
66
+ ...mapState("edit", [
67
+ "editMode",
68
+ "documentPagesListForEditMode",
69
+ "pagesForPostprocess",
70
+ ]),
71
+ ...mapState("display", [
72
+ "scale",
73
+ "documentActionBar",
74
+ "pageChangedFromThumbnail",
75
+ "currentPage",
76
+ ]),
77
+ ...mapGetters("display", ["visiblePageRange"]),
78
+
79
+ pages() {
80
+ if (this.selectedDocument) {
81
+ return this.selectedDocument.pages;
82
+ } else {
83
+ return [];
84
+ }
85
+ },
86
+ showToolbar() {
87
+ return (
88
+ !this.loading &&
89
+ this.pages.length > 0 &&
90
+ this.scale &&
91
+ !this.documentActionBar
92
+ );
93
+ },
94
+ showActionBar() {
95
+ return this.documentActionBar !== null;
96
+ },
97
+ },
98
+ watch: {
99
+ loading() {
100
+ this.scrollTop = 0;
101
+ },
102
+ },
103
+ mounted() {
104
+ this.$refs.scrollingDocument.addEventListener("scroll", this.handleScroll);
105
+ },
106
+
107
+ methods: {
108
+ updateScrollBounds() {
109
+ const { scrollTop, clientHeight } = this.$refs.scrollingDocument;
110
+ this.scrollTop = scrollTop;
111
+ this.clientHeight = clientHeight;
112
+ },
113
+ /**
114
+ * Scrolls the ScrollingDocument to the offset specified by scrollTop & scrollLeft (if zoomed in)
115
+ * (i.e., another page).
116
+ */
117
+ onPageJump(scrollTop, scrollLeft) {
118
+ const scrollY = scrollTop - (this.$refs.scrollingDocument.offsetTop + 4); // + 4 due to margin between pages
119
+ const scrollX = scrollLeft - this.$refs.scrollingDocument.offsetLeft - 4; // - 4 to add more space before the entity
120
+
121
+ this.$refs.scrollingDocument.scroll(scrollX, scrollY);
122
+ },
123
+ handleScroll() {
124
+ if (this.pages.length === 1) return;
125
+
126
+ this.isScrolling = true;
127
+
128
+ clearTimeout(this.scrollTimeout);
129
+
130
+ this.scrollTimeout = setTimeout(() => {
131
+ this.isScrolling = false;
132
+
133
+ if (
134
+ this.pageChangedFromThumbnail &&
135
+ this.visiblePageRange[1] === this.currentPage
136
+ ) {
137
+ this.$store.dispatch("display/setPageChangedFromThumbnail", false);
138
+ }
139
+ }, 300);
140
+ },
141
+ },
142
+ };
143
+ </script>
144
+
145
+ <style
146
+ scoped
147
+ lang="scss"
148
+ src="../../assets/scss/scrolling_document.scss"
149
+ ></style>
@@ -1,179 +1,179 @@
1
- <template>
2
- <div>
3
- <DummyPage
4
- v-if="!loadedPage || !pageInVisibleRange(page)"
5
- :width="page.size[0]"
6
- :height="page.size[1]"
7
- />
8
- <DocumentPage v-else :page="loadedPage" />
9
- </div>
10
- </template>
11
-
12
- <script>
13
- import { mapGetters, mapState } from "vuex";
14
- import DocumentPage from "../DocumentPage/DocumentPage";
15
- import DummyPage from "../DocumentPage/DummyPage";
16
-
17
- export default {
18
- name: "ScrollingPage",
19
-
20
- components: {
21
- DocumentPage,
22
- DummyPage,
23
- },
24
-
25
- props: {
26
- page: {
27
- type: Object,
28
- required: true,
29
- },
30
- scrollTop: {
31
- type: Number,
32
- required: true,
33
- },
34
- clientHeight: {
35
- type: Number,
36
- required: true,
37
- },
38
- },
39
-
40
- data() {
41
- return {
42
- elementTop: 0,
43
- elementHeight: 0,
44
- previousFocusedAnnotation: null,
45
- previousY: null,
46
- pageBeingLoaded: false,
47
- isScrolling: false,
48
- };
49
- },
50
-
51
- computed: {
52
- ...mapState("display", ["pageChangedFromThumbnail"]),
53
- ...mapGetters("display", ["visiblePageRange", "bboxToRect"]),
54
- ...mapGetters("document", ["scrollDocumentToAnnotation"]),
55
-
56
- loadedPage() {
57
- if (this.editMode) {
58
- return this.page;
59
- }
60
- let loadedPage = null;
61
- if (this.page && this.pages) {
62
- loadedPage = this.pages.find((p) => p.number === this.page.number);
63
- }
64
- if (!loadedPage && this.pageInVisibleRange(this.page)) {
65
- if (!this.pageBeingLoaded) {
66
- this.loadPage();
67
- }
68
- }
69
- return loadedPage;
70
- },
71
-
72
- isElementFocused() {
73
- const { elementTop, bottom, elementHeight, scrollTop, clientHeight } =
74
- this;
75
- if (!elementHeight) return;
76
-
77
- const halfHeight = elementHeight / 2;
78
- const halfScreen = clientHeight / 2;
79
- const delta = elementHeight >= halfScreen ? halfScreen : halfHeight;
80
- const threshold = scrollTop + delta;
81
-
82
- return elementTop < threshold && bottom >= threshold;
83
- },
84
-
85
- bottom() {
86
- return this.elementTop + this.elementHeight;
87
- },
88
-
89
- scrollBottom() {
90
- return this.scrollTop + this.clientHeight;
91
- },
92
-
93
- ...mapState("display", ["currentPage"]),
94
- ...mapState("document", ["pages", "documentAnnotationSelected", "loading"]),
95
- ...mapState("edit", ["editMode"]),
96
- },
97
-
98
- watch: {
99
- scrollTop: "updateElementBounds",
100
- clientHeight: "updateElementBounds",
101
-
102
- /**
103
- * Scroll to the focused annotation if it changes and it's on this page.
104
- */
105
- scrollDocumentToAnnotation(isToScroll) {
106
- if (
107
- isToScroll &&
108
- this.documentAnnotationSelected.page === this.page.number
109
- ) {
110
- // We wait for the page to be focused before actually scrolling
111
- // to the focused annotation.
112
- this.$nextTick(() => {
113
- // Scroll to the annotation
114
- this.scrollTo(
115
- this.getYForBbox(this.documentAnnotationSelected.span),
116
- this.getXForBbox(this.documentAnnotationSelected.span)
117
- );
118
- });
119
- }
120
- },
121
- isElementFocused(focused) {
122
- if (!this.loading && focused && !this.pageChangedFromThumbnail) {
123
- this.$store.dispatch("display/updateCurrentPage", this.page.number);
124
- }
125
- },
126
- currentPage(number) {
127
- if (this.page.number === number && !this.isElementFocused) {
128
- this.$emit("page-jump", this.elementTop, 0);
129
- }
130
- },
131
- },
132
- mounted() {
133
- this.updateElementBounds();
134
- },
135
-
136
- methods: {
137
- loadPage() {
138
- this.pageBeingLoaded = true;
139
- this.$store
140
- .dispatch("document/fetchDocumentPage", this.page.number)
141
- .then(() => {
142
- this.pageBeingLoaded = false;
143
- });
144
- },
145
- pageInVisibleRange(page) {
146
- return (
147
- this.currentPage === page.number ||
148
- this.visiblePageRange.includes(page.number)
149
- );
150
- },
151
- updateElementBounds() {
152
- const { offsetTop, offsetHeight } = this.$el;
153
- this.elementTop = offsetTop;
154
- this.elementHeight = offsetHeight;
155
- },
156
-
157
- /**
158
- * Calculate the y-position of this bbox on the page
159
- * from its top, the scale and the image scale (calculated
160
- * from the page object).
161
- */
162
- getYForBbox(bbox) {
163
- return this.bboxToRect(this.page, bbox).y;
164
- },
165
-
166
- getXForBbox(bbox) {
167
- return this.bboxToRect(this.page, bbox).x;
168
- },
169
-
170
- /**
171
- * Scroll to a relative position in the page. It gets added
172
- * the page's element top and a padding margin.
173
- */
174
- scrollTo(y, x) {
175
- this.$emit("page-jump", this.elementTop + y - 80, x);
176
- },
177
- },
178
- };
179
- </script>
1
+ <template>
2
+ <div>
3
+ <DummyPage
4
+ v-if="!loadedPage || !pageInVisibleRange(page)"
5
+ :width="page.size[0]"
6
+ :height="page.size[1]"
7
+ />
8
+ <DocumentPage v-else :page="loadedPage" />
9
+ </div>
10
+ </template>
11
+
12
+ <script>
13
+ import { mapGetters, mapState } from "vuex";
14
+ import DocumentPage from "../DocumentPage/DocumentPage";
15
+ import DummyPage from "../DocumentPage/DummyPage";
16
+
17
+ export default {
18
+ name: "ScrollingPage",
19
+
20
+ components: {
21
+ DocumentPage,
22
+ DummyPage,
23
+ },
24
+
25
+ props: {
26
+ page: {
27
+ type: Object,
28
+ required: true,
29
+ },
30
+ scrollTop: {
31
+ type: Number,
32
+ required: true,
33
+ },
34
+ clientHeight: {
35
+ type: Number,
36
+ required: true,
37
+ },
38
+ },
39
+
40
+ data() {
41
+ return {
42
+ elementTop: 0,
43
+ elementHeight: 0,
44
+ previousFocusedAnnotation: null,
45
+ previousY: null,
46
+ pageBeingLoaded: false,
47
+ isScrolling: false,
48
+ };
49
+ },
50
+
51
+ computed: {
52
+ ...mapState("display", ["pageChangedFromThumbnail"]),
53
+ ...mapGetters("display", ["visiblePageRange", "bboxToRect"]),
54
+ ...mapGetters("document", ["scrollDocumentToAnnotation"]),
55
+
56
+ loadedPage() {
57
+ if (this.editMode) {
58
+ return this.page;
59
+ }
60
+ let loadedPage = null;
61
+ if (this.page && this.pages) {
62
+ loadedPage = this.pages.find((p) => p.number === this.page.number);
63
+ }
64
+ if (!loadedPage && this.pageInVisibleRange(this.page)) {
65
+ if (!this.pageBeingLoaded) {
66
+ this.loadPage();
67
+ }
68
+ }
69
+ return loadedPage;
70
+ },
71
+
72
+ isElementFocused() {
73
+ const { elementTop, bottom, elementHeight, scrollTop, clientHeight } =
74
+ this;
75
+ if (!elementHeight) return;
76
+
77
+ const halfHeight = elementHeight / 2;
78
+ const halfScreen = clientHeight / 2;
79
+ const delta = elementHeight >= halfScreen ? halfScreen : halfHeight;
80
+ const threshold = scrollTop + delta;
81
+
82
+ return elementTop < threshold && bottom >= threshold;
83
+ },
84
+
85
+ bottom() {
86
+ return this.elementTop + this.elementHeight;
87
+ },
88
+
89
+ scrollBottom() {
90
+ return this.scrollTop + this.clientHeight;
91
+ },
92
+
93
+ ...mapState("display", ["currentPage"]),
94
+ ...mapState("document", ["pages", "documentAnnotationSelected", "loading"]),
95
+ ...mapState("edit", ["editMode"]),
96
+ },
97
+
98
+ watch: {
99
+ scrollTop: "updateElementBounds",
100
+ clientHeight: "updateElementBounds",
101
+
102
+ /**
103
+ * Scroll to the focused annotation if it changes and it's on this page.
104
+ */
105
+ scrollDocumentToAnnotation(isToScroll) {
106
+ if (
107
+ isToScroll &&
108
+ this.documentAnnotationSelected.page === this.page.number
109
+ ) {
110
+ // We wait for the page to be focused before actually scrolling
111
+ // to the focused annotation.
112
+ this.$nextTick(() => {
113
+ // Scroll to the annotation
114
+ this.scrollTo(
115
+ this.getYForBbox(this.documentAnnotationSelected.span),
116
+ this.getXForBbox(this.documentAnnotationSelected.span)
117
+ );
118
+ });
119
+ }
120
+ },
121
+ isElementFocused(focused) {
122
+ if (!this.loading && focused && !this.pageChangedFromThumbnail) {
123
+ this.$store.dispatch("display/updateCurrentPage", this.page.number);
124
+ }
125
+ },
126
+ currentPage(number) {
127
+ if (this.page.number === number && !this.isElementFocused) {
128
+ this.$emit("page-jump", this.elementTop, 0);
129
+ }
130
+ },
131
+ },
132
+ mounted() {
133
+ this.updateElementBounds();
134
+ },
135
+
136
+ methods: {
137
+ loadPage() {
138
+ this.pageBeingLoaded = true;
139
+ this.$store
140
+ .dispatch("document/fetchDocumentPage", this.page.number)
141
+ .then(() => {
142
+ this.pageBeingLoaded = false;
143
+ });
144
+ },
145
+ pageInVisibleRange(page) {
146
+ return (
147
+ this.currentPage === page.number ||
148
+ this.visiblePageRange.includes(page.number)
149
+ );
150
+ },
151
+ updateElementBounds() {
152
+ const { offsetTop, offsetHeight } = this.$el;
153
+ this.elementTop = offsetTop;
154
+ this.elementHeight = offsetHeight;
155
+ },
156
+
157
+ /**
158
+ * Calculate the y-position of this bbox on the page
159
+ * from its top, the scale and the image scale (calculated
160
+ * from the page object).
161
+ */
162
+ getYForBbox(bbox) {
163
+ return this.bboxToRect(this.page, bbox).y;
164
+ },
165
+
166
+ getXForBbox(bbox) {
167
+ return this.bboxToRect(this.page, bbox).x;
168
+ },
169
+
170
+ /**
171
+ * Scroll to a relative position in the page. It gets added
172
+ * the page's element top and a padding margin.
173
+ */
174
+ scrollTo(y, x) {
175
+ this.$emit("page-jump", this.elementTop + y - 80, x);
176
+ },
177
+ },
178
+ };
179
+ </script>
@@ -1,5 +1,5 @@
1
- export { default as DocumentPage } from "./DocumentPage";
2
- export { default as DummyPage } from "./DummyPage";
3
- export { default as ScrollingDocument } from "./ScrollingDocument";
4
- export { default as ScrollingPage } from "./ScrollingPage";
5
- export { default as ToolBar } from "./DocumentToolbar";
1
+ export { default as DocumentPage } from "./DocumentPage";
2
+ export { default as DummyPage } from "./DummyPage";
3
+ export { default as ScrollingDocument } from "./ScrollingDocument";
4
+ export { default as ScrollingPage } from "./ScrollingPage";
5
+ export { default as ToolBar } from "./DocumentToolbar";