@konfuzio/document-validation-ui 0.1.24-dev.0 → 0.1.24-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/css/app.css +1 -1
- package/dist/index.html +1 -1
- package/dist/js/app.js +1 -1
- package/dist/js/app.js.map +1 -1
- package/dist/js/chunk-vendors.js +1 -1
- package/dist/js/chunk-vendors.js.map +1 -1
- package/package.json +1 -1
- package/src/assets/scss/document_annotations.scss +5 -1
- package/src/assets/scss/document_search_bar.scss +71 -0
- package/src/assets/scss/document_toolbar.scss +2 -1
- package/src/assets/scss/theme.scss +2 -1
- package/src/assets/scss/variables.scss +1 -0
- package/src/components/App.vue +16 -0
- package/src/components/DocumentAnnotations/AnnotationActionButtons.vue +10 -0
- package/src/components/DocumentAnnotations/AnnotationRow.vue +11 -6
- package/src/components/DocumentAnnotations/DocumentAnnotations.vue +4 -5
- package/src/components/DocumentPage/DocumentPage.cy.js +82 -1
- package/src/components/DocumentPage/DocumentPage.vue +41 -1
- package/src/components/DocumentPage/DocumentToolbar.cy.js +12 -0
- package/src/components/DocumentPage/DocumentToolbar.vue +9 -1
- package/src/components/DocumentPage/NewAnnotation.vue +6 -2
- package/src/components/DocumentPage/ScrollingDocument.vue +6 -0
- package/src/components/DocumentPage/ScrollingPage.vue +26 -4
- package/src/components/DocumentPage/SearchBar.vue +130 -0
- package/src/components/DocumentTopBar/DocumentName.vue +10 -2
- package/src/icons.js +3 -1
- package/src/locales/de.json +7 -1
- package/src/locales/en.json +8 -1
- package/src/locales/es.json +7 -1
- package/src/store/display.js +114 -0
- package/src/store/document.js +1 -2
package/package.json
CHANGED
|
@@ -515,8 +515,12 @@
|
|
|
515
515
|
|
|
516
516
|
.missing-button-container {
|
|
517
517
|
background-color: transparent;
|
|
518
|
+
display: flex;
|
|
519
|
+
flex-direction: row;
|
|
518
520
|
|
|
519
|
-
.missing-btn
|
|
521
|
+
.missing-btn,
|
|
522
|
+
.search-btn {
|
|
523
|
+
padding: 6px;
|
|
520
524
|
color: $grey-blue !important;
|
|
521
525
|
font-size: 14px !important;
|
|
522
526
|
font-weight: 500;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
@import "./imports.scss";
|
|
2
|
+
#document-search {
|
|
3
|
+
position: absolute;
|
|
4
|
+
right: 8px;
|
|
5
|
+
min-width: 276px;
|
|
6
|
+
width: fit-content;
|
|
7
|
+
z-index: 95;
|
|
8
|
+
|
|
9
|
+
.search-container {
|
|
10
|
+
background-color: $searchbar;
|
|
11
|
+
color: $white;
|
|
12
|
+
height: 40px;
|
|
13
|
+
padding: 8px 4px;
|
|
14
|
+
border-radius: 8px;
|
|
15
|
+
display: flex;
|
|
16
|
+
flex-direction: row;
|
|
17
|
+
justify-content: space-between;
|
|
18
|
+
align-items: center;
|
|
19
|
+
|
|
20
|
+
.button {
|
|
21
|
+
background: none;
|
|
22
|
+
color: inherit;
|
|
23
|
+
|
|
24
|
+
&:disabled {
|
|
25
|
+
pointer-events: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
&:hover {
|
|
29
|
+
background: $low-opacity-white;
|
|
30
|
+
border-radius: 4px;
|
|
31
|
+
color: inherit;
|
|
32
|
+
}
|
|
33
|
+
.icon {
|
|
34
|
+
vertical-align: middle;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.search-input {
|
|
39
|
+
margin-left: 8px;
|
|
40
|
+
flex: 1;
|
|
41
|
+
font-size: 14px;
|
|
42
|
+
background: inherit;
|
|
43
|
+
color: inherit;
|
|
44
|
+
border: 0;
|
|
45
|
+
outline: none;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.search-no-results {
|
|
49
|
+
color: $text-lighter;
|
|
50
|
+
font-size: 12px;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.search-navigation {
|
|
54
|
+
display: flex;
|
|
55
|
+
flex-direction: row;
|
|
56
|
+
align-items: center;
|
|
57
|
+
|
|
58
|
+
.search-counters {
|
|
59
|
+
font-size: 12px;
|
|
60
|
+
margin-right: 6px;
|
|
61
|
+
color: $text-lighter;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.search-loading {
|
|
66
|
+
display: flex;
|
|
67
|
+
font-size: 12px;
|
|
68
|
+
color: $text-lighter;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
package/src/components/App.vue
CHANGED
|
@@ -72,6 +72,12 @@ export default {
|
|
|
72
72
|
required: false,
|
|
73
73
|
default: "",
|
|
74
74
|
},
|
|
75
|
+
// eslint-disable-next-line vue/prop-name-casing
|
|
76
|
+
details_url: {
|
|
77
|
+
type: String,
|
|
78
|
+
required: false,
|
|
79
|
+
default: "",
|
|
80
|
+
},
|
|
75
81
|
},
|
|
76
82
|
computed: {
|
|
77
83
|
documentId() {
|
|
@@ -115,6 +121,15 @@ export default {
|
|
|
115
121
|
return null;
|
|
116
122
|
}
|
|
117
123
|
},
|
|
124
|
+
detailsUrl() {
|
|
125
|
+
if (process.env.VUE_APP_DOCUMENT_DETAILS_URL) {
|
|
126
|
+
return process.env.VUE_APP_DOCUMENT_DETAILS_URL;
|
|
127
|
+
} else if (this.details_url) {
|
|
128
|
+
return this.details_url;
|
|
129
|
+
} else {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
},
|
|
118
133
|
},
|
|
119
134
|
created() {
|
|
120
135
|
// Sentry config
|
|
@@ -156,6 +171,7 @@ export default {
|
|
|
156
171
|
|
|
157
172
|
// document and project config
|
|
158
173
|
Promise.all([
|
|
174
|
+
this.$store.dispatch("display/setDetailsUrl", this.detailsUrl),
|
|
159
175
|
this.$store.dispatch("document/setDocId", this.documentId),
|
|
160
176
|
this.$store.dispatch("document/setPublicView", this.isPublicView),
|
|
161
177
|
this.$store.dispatch(
|
|
@@ -59,6 +59,13 @@
|
|
|
59
59
|
<b-button type="is-ghost" class="missing-btn" @click.stop="markAsMissing">
|
|
60
60
|
{{ $t("missing_annotation") }}
|
|
61
61
|
</b-button>
|
|
62
|
+
<b-button
|
|
63
|
+
type="is-ghost"
|
|
64
|
+
class="search-btn"
|
|
65
|
+
@click.stop="searchInDocument"
|
|
66
|
+
>
|
|
67
|
+
{{ $t("search_in_document") }}
|
|
68
|
+
</b-button>
|
|
62
69
|
</div>
|
|
63
70
|
|
|
64
71
|
<!-- Restore not found annotations -->
|
|
@@ -141,6 +148,9 @@ export default {
|
|
|
141
148
|
restore() {
|
|
142
149
|
this.$emit("restore");
|
|
143
150
|
},
|
|
151
|
+
searchInDocument() {
|
|
152
|
+
this.$emit("search-label-in-document");
|
|
153
|
+
},
|
|
144
154
|
},
|
|
145
155
|
};
|
|
146
156
|
</script>
|
|
@@ -137,12 +137,13 @@
|
|
|
137
137
|
:save-btn="showSaveButton()"
|
|
138
138
|
:restore-btn="showRestoreButton()"
|
|
139
139
|
:is-loading="isLoading"
|
|
140
|
-
@mark-as-missing="handleMissingAnnotation
|
|
141
|
-
@save="handleSaveChanges
|
|
142
|
-
@accept="handleSaveChanges
|
|
140
|
+
@mark-as-missing="handleMissingAnnotation"
|
|
141
|
+
@save="handleSaveChanges"
|
|
142
|
+
@accept="handleSaveChanges"
|
|
143
143
|
@decline="handleSaveChanges(true)"
|
|
144
|
-
@cancel="handleCancelButton
|
|
145
|
-
@restore="handleRestore
|
|
144
|
+
@cancel="handleCancelButton"
|
|
145
|
+
@restore="handleRestore"
|
|
146
|
+
@search-label-in-document="searchLabelInDocument"
|
|
146
147
|
/>
|
|
147
148
|
</div>
|
|
148
149
|
</div>
|
|
@@ -511,7 +512,7 @@ export default {
|
|
|
511
512
|
false
|
|
512
513
|
);
|
|
513
514
|
},
|
|
514
|
-
handleSaveChanges(decline) {
|
|
515
|
+
handleSaveChanges(decline = false) {
|
|
515
516
|
if (this.publicView || this.isDocumentReviewed) return;
|
|
516
517
|
|
|
517
518
|
// Verify if we are editing a filled or empty annotation
|
|
@@ -732,6 +733,10 @@ export default {
|
|
|
732
733
|
|
|
733
734
|
window.open(annotationDetailsUrl, "_blank");
|
|
734
735
|
},
|
|
736
|
+
searchLabelInDocument() {
|
|
737
|
+
this.$store.dispatch("display/enableSearch", true);
|
|
738
|
+
this.$store.dispatch("display/setCurrentSearch", this.label.name);
|
|
739
|
+
},
|
|
735
740
|
},
|
|
736
741
|
};
|
|
737
742
|
</script>
|
|
@@ -63,8 +63,7 @@
|
|
|
63
63
|
:icon="
|
|
64
64
|
annotationSetsAccordion[indexGroup] ? 'angle-up' : 'angle-down'
|
|
65
65
|
"
|
|
66
|
-
|
|
67
|
-
</b-icon>
|
|
66
|
+
/>
|
|
68
67
|
{{
|
|
69
68
|
`${annotationSet.label_set.name} ${numberOfAnnotationSetGroup(
|
|
70
69
|
annotationSet
|
|
@@ -388,9 +387,6 @@ export default {
|
|
|
388
387
|
// Not allow starting edit mode with ArrowUp key
|
|
389
388
|
if (event.key === "ArrowUp" && !this.isAnnotationBeingEdited) return;
|
|
390
389
|
|
|
391
|
-
// open accordions
|
|
392
|
-
this.openAllAccordions();
|
|
393
|
-
|
|
394
390
|
// Get all the annotation elements
|
|
395
391
|
let annotations = this.createArray("keyboard-nav");
|
|
396
392
|
|
|
@@ -404,6 +400,9 @@ export default {
|
|
|
404
400
|
|
|
405
401
|
// navigate with the arrow up or down keys
|
|
406
402
|
if (event.key === "ArrowDown") {
|
|
403
|
+
// open accordions
|
|
404
|
+
this.openAllAccordions();
|
|
405
|
+
|
|
407
406
|
// Check if we are focusing on the Finish Review button
|
|
408
407
|
if (this.count >= annotations.length) {
|
|
409
408
|
const finishBtn = this.createArray("finish-review-btn");
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import DocumentDashboard from "../DocumentDashboard.vue";
|
|
2
1
|
import DocumentPage from "../DocumentPage/DocumentPage.vue";
|
|
2
|
+
import SearchBar from "../DocumentPage/SearchBar.vue";
|
|
3
3
|
|
|
4
4
|
const viewport = {
|
|
5
5
|
width: 1280,
|
|
@@ -13,6 +13,87 @@ describe("Document Page", () => {
|
|
|
13
13
|
cy.viewport(viewport.width, viewport.height);
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
+
it("Search for text in the document", () => {
|
|
17
|
+
cy.getStore("document").then(($document) => {
|
|
18
|
+
if ($document.selectedDocument.pages[0]) {
|
|
19
|
+
cy.setScale($document.selectedDocument.pages[0]);
|
|
20
|
+
cy.fetchBlob(
|
|
21
|
+
`${$document.selectedDocument.pages[0].image_url}?${$document.selectedDocument.downloaded_at}`
|
|
22
|
+
).then((blob) => {
|
|
23
|
+
cy.mount(SearchBar).then(({ wrapper, component }) => {
|
|
24
|
+
if ($document.pages && $document.pages.length > 0) {
|
|
25
|
+
const entities = $document.pages.flatMap((page) => {
|
|
26
|
+
return page.entities;
|
|
27
|
+
});
|
|
28
|
+
let entity;
|
|
29
|
+
do {
|
|
30
|
+
entity = entities[Math.floor(Math.random() * entities.length)]; // get a random entity
|
|
31
|
+
} while (!entity || entity.offset_string.length < 3);
|
|
32
|
+
|
|
33
|
+
cy.dispatchAction("display", "enableSearch", true);
|
|
34
|
+
cy.dispatchAction(
|
|
35
|
+
"display",
|
|
36
|
+
"setCurrentSearch",
|
|
37
|
+
entity.offset_string
|
|
38
|
+
);
|
|
39
|
+
cy.wait(2000);
|
|
40
|
+
cy.getStore("display").then(($display) => {
|
|
41
|
+
expect($display.searchResults.length).to.be.greaterThan(0);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
} else {
|
|
47
|
+
throw new Error("Document not loaded");
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("Navigate to next search result if exists", () => {
|
|
53
|
+
cy.getStore("document").then(($document) => {
|
|
54
|
+
if ($document.selectedDocument.pages[0]) {
|
|
55
|
+
cy.setScale($document.selectedDocument.pages[0]);
|
|
56
|
+
cy.fetchBlob(
|
|
57
|
+
`${$document.selectedDocument.pages[0].image_url}?${$document.selectedDocument.downloaded_at}`
|
|
58
|
+
).then((blob) => {
|
|
59
|
+
cy.mount(SearchBar).then(({ wrapper, component }) => {
|
|
60
|
+
cy.wait(2000);
|
|
61
|
+
if ($document.pages && $document.pages.length > 0) {
|
|
62
|
+
const entities = $document.pages.flatMap((page) => {
|
|
63
|
+
return page.entities;
|
|
64
|
+
});
|
|
65
|
+
let entity;
|
|
66
|
+
do {
|
|
67
|
+
entity = entities[Math.floor(Math.random() * entities.length)]; // get a random entity
|
|
68
|
+
} while (!entity || entity.offset_string.length < 3);
|
|
69
|
+
|
|
70
|
+
cy.dispatchAction("display", "enableSearch", true);
|
|
71
|
+
cy.dispatchAction(
|
|
72
|
+
"display",
|
|
73
|
+
"setCurrentSearch",
|
|
74
|
+
entity.offset_string
|
|
75
|
+
);
|
|
76
|
+
cy.wait(2000);
|
|
77
|
+
cy.getStore("display").then(($display) => {
|
|
78
|
+
if ($display.searchResults.length > 1) {
|
|
79
|
+
expect(component.currentCounter).to.be.eql(1);
|
|
80
|
+
cy.get("#document-search .next-search").click();
|
|
81
|
+
cy.getStore("display").then(() => {
|
|
82
|
+
expect(component.currentCounter).to.be.eql(2);
|
|
83
|
+
});
|
|
84
|
+
} else {
|
|
85
|
+
cy.get("#document-search .next-search").should("be.disabled");
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
} else {
|
|
92
|
+
throw new Error("Document not loaded");
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
16
97
|
it("All annotations appear at the right place", () => {
|
|
17
98
|
cy.getStore("document").then(($document) => {
|
|
18
99
|
if (
|
|
@@ -51,6 +51,15 @@
|
|
|
51
51
|
}"
|
|
52
52
|
/>
|
|
53
53
|
<template v-if="pageInVisibleRange && !editMode">
|
|
54
|
+
<template v-if="searchResults.length > 0">
|
|
55
|
+
<v-rect
|
|
56
|
+
v-for="(bbox, index) in searchResults"
|
|
57
|
+
:key="'sr' + index"
|
|
58
|
+
:config="{
|
|
59
|
+
...selectionTextRect(bbox, bbox === currentSearchResultForPage),
|
|
60
|
+
}"
|
|
61
|
+
></v-rect>
|
|
62
|
+
</template>
|
|
54
63
|
<v-group v-if="!publicView || !isDocumentReviewed" ref="entities">
|
|
55
64
|
<v-rect
|
|
56
65
|
v-for="(entity, index) in scaledEntities"
|
|
@@ -266,8 +275,25 @@ export default {
|
|
|
266
275
|
);
|
|
267
276
|
},
|
|
268
277
|
|
|
278
|
+
searchResults() {
|
|
279
|
+
const results = this.$store.getters["display/searchResultsForPage"](
|
|
280
|
+
this.page.number
|
|
281
|
+
);
|
|
282
|
+
return results;
|
|
283
|
+
},
|
|
284
|
+
|
|
285
|
+
currentSearchResultForPage() {
|
|
286
|
+
return this.$store.getters["display/currentSearchResultForPage"](
|
|
287
|
+
this.page.number
|
|
288
|
+
);
|
|
289
|
+
},
|
|
290
|
+
|
|
269
291
|
...mapState("selection", ["isSelecting", "selectedEntities"]),
|
|
270
|
-
...mapState("display", [
|
|
292
|
+
...mapState("display", [
|
|
293
|
+
"scale",
|
|
294
|
+
"categorizeModalIsActive",
|
|
295
|
+
"searchEnabled",
|
|
296
|
+
]),
|
|
271
297
|
...mapState("document", [
|
|
272
298
|
"documentAnnotationSelected",
|
|
273
299
|
"recalculatingAnnotations",
|
|
@@ -308,6 +334,11 @@ export default {
|
|
|
308
334
|
this.drawPage(true);
|
|
309
335
|
}
|
|
310
336
|
},
|
|
337
|
+
searchEnabled(isEnabled) {
|
|
338
|
+
if (isEnabled) {
|
|
339
|
+
this.closePopups(true);
|
|
340
|
+
}
|
|
341
|
+
},
|
|
311
342
|
},
|
|
312
343
|
mounted() {
|
|
313
344
|
if (
|
|
@@ -495,6 +526,15 @@ export default {
|
|
|
495
526
|
}
|
|
496
527
|
},
|
|
497
528
|
|
|
529
|
+
selectionTextRect(bbox, isFocused) {
|
|
530
|
+
return {
|
|
531
|
+
fill: isFocused ? "orange" : "greenyellow",
|
|
532
|
+
stroke: isFocused ? "orange" : "",
|
|
533
|
+
globalCompositeOperation: "multiply",
|
|
534
|
+
...this.bboxToRect(this.page, bbox),
|
|
535
|
+
};
|
|
536
|
+
},
|
|
537
|
+
|
|
498
538
|
/**
|
|
499
539
|
* Builds the konva config object for the entity.
|
|
500
540
|
*/
|
|
@@ -6,6 +6,18 @@ describe("Document Toolbar", () => {
|
|
|
6
6
|
cy.setFullMode();
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
+
it("open document search", () => {
|
|
10
|
+
cy.mount(DocumentDashboard).then(({ wrapper, component }) => {
|
|
11
|
+
component.onDocumentResize();
|
|
12
|
+
cy.get("#toolbar-container").find(".search-document").first().click();
|
|
13
|
+
|
|
14
|
+
cy.getStore("display").then(($display) => {
|
|
15
|
+
expect($display.searchEnabled).to.eql(true);
|
|
16
|
+
cy.get("#document-search").should("exist");
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
|
|
9
21
|
it("downloads the original file", () => {
|
|
10
22
|
cy.mount(DocumentDashboard).then(({ wrapper, component }) => {
|
|
11
23
|
component.onDocumentResize();
|
|
@@ -24,6 +24,13 @@
|
|
|
24
24
|
</div>
|
|
25
25
|
</b-tooltip>
|
|
26
26
|
<div v-if="isEditModeAvailable" class="toolbar-divider" />
|
|
27
|
+
<div
|
|
28
|
+
v-if="!publicView"
|
|
29
|
+
class="search-document icons"
|
|
30
|
+
@click="toggleSearch"
|
|
31
|
+
>
|
|
32
|
+
<b-icon icon="search" size="small" class="search-icon" />
|
|
33
|
+
</div>
|
|
27
34
|
|
|
28
35
|
<div v-if="!publicView" class="download-file icons">
|
|
29
36
|
<b-dropdown aria-role="list" position="is-top-right" scrollable>
|
|
@@ -80,7 +87,7 @@
|
|
|
80
87
|
</template>
|
|
81
88
|
|
|
82
89
|
<script>
|
|
83
|
-
import { mapState, mapGetters } from "vuex";
|
|
90
|
+
import { mapActions, mapState, mapGetters } from "vuex";
|
|
84
91
|
import FitZoomIcon from "../../assets/images/FitZoomIcon";
|
|
85
92
|
import PlusIcon from "../../assets/images/PlusIcon";
|
|
86
93
|
import MinusIcon from "../../assets/images/MinusIcon";
|
|
@@ -144,6 +151,7 @@ export default {
|
|
|
144
151
|
}
|
|
145
152
|
},
|
|
146
153
|
methods: {
|
|
154
|
+
...mapActions("display", ["toggleSearch"]),
|
|
147
155
|
handleEdit() {
|
|
148
156
|
if (this.editModeDisabled) return;
|
|
149
157
|
this.$store.dispatch("selection/disableSelection");
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="annotation-popup" :style="{ left: `${left}px`, top: `${top}px` }">
|
|
3
|
-
<
|
|
3
|
+
<div v-if="!textFromEntities" class="popup-input">
|
|
4
|
+
<b-icon icon="spinner" class="fa-spin loading-icon-size spinner" />
|
|
5
|
+
</div>
|
|
6
|
+
<input v-else v-model="textFromEntities" class="popup-input" type="text" />
|
|
4
7
|
<b-dropdown
|
|
5
8
|
v-model="selectedSet"
|
|
9
|
+
:disabled="!textFromEntities"
|
|
6
10
|
aria-role="list"
|
|
7
11
|
:class="[
|
|
8
12
|
'annotation-dropdown',
|
|
@@ -70,7 +74,7 @@
|
|
|
70
74
|
<b-dropdown
|
|
71
75
|
v-model="selectedLabel"
|
|
72
76
|
aria-role="list"
|
|
73
|
-
:disabled="!labels || labels.length === 0"
|
|
77
|
+
:disabled="!textFromEntities || !labels || labels.length === 0"
|
|
74
78
|
scrollable
|
|
75
79
|
class="label-dropdown annotation-dropdown"
|
|
76
80
|
>
|
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
v-scroll.immediate="updateScrollBounds"
|
|
6
6
|
class="scrolling-document"
|
|
7
7
|
>
|
|
8
|
+
<transition :name="searchEnabled ? 'slide-down' : 'slide-up'">
|
|
9
|
+
<SearchBar v-if="searchEnabled" />
|
|
10
|
+
</transition>
|
|
8
11
|
<div
|
|
9
12
|
v-if="
|
|
10
13
|
selectedDocument && scale && !loading && !recalculatingAnnotations
|
|
@@ -36,12 +39,14 @@ import scroll from "../../directives/scroll";
|
|
|
36
39
|
import ScrollingPage from "./ScrollingPage";
|
|
37
40
|
import Toolbar from "./DocumentToolbar";
|
|
38
41
|
import ActionBar from "./ActionBar";
|
|
42
|
+
import SearchBar from "./SearchBar";
|
|
39
43
|
|
|
40
44
|
export default {
|
|
41
45
|
components: {
|
|
42
46
|
ScrollingPage,
|
|
43
47
|
Toolbar,
|
|
44
48
|
ActionBar,
|
|
49
|
+
SearchBar,
|
|
45
50
|
},
|
|
46
51
|
directives: {
|
|
47
52
|
scroll,
|
|
@@ -73,6 +78,7 @@ export default {
|
|
|
73
78
|
"documentActionBar",
|
|
74
79
|
"pageChangedFromThumbnail",
|
|
75
80
|
"currentPage",
|
|
81
|
+
"searchEnabled",
|
|
76
82
|
]),
|
|
77
83
|
...mapGetters("display", ["visiblePageRange"]),
|
|
78
84
|
|
|
@@ -49,7 +49,9 @@ export default {
|
|
|
49
49
|
},
|
|
50
50
|
|
|
51
51
|
computed: {
|
|
52
|
-
...mapState("display", ["pageChangedFromThumbnail"]),
|
|
52
|
+
...mapState("display", ["pageChangedFromThumbnail", "currentPage"]),
|
|
53
|
+
...mapState("document", ["pages", "documentAnnotationSelected", "loading"]),
|
|
54
|
+
...mapState("edit", ["editMode"]),
|
|
53
55
|
...mapGetters("display", ["visiblePageRange", "bboxToRect"]),
|
|
54
56
|
...mapGetters("document", ["scrollDocumentToAnnotation"]),
|
|
55
57
|
|
|
@@ -90,9 +92,11 @@ export default {
|
|
|
90
92
|
return this.scrollTop + this.clientHeight;
|
|
91
93
|
},
|
|
92
94
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
95
|
+
currentSearchResultForPage() {
|
|
96
|
+
return this.$store.getters["display/currentSearchResultForPage"](
|
|
97
|
+
this.page.number
|
|
98
|
+
);
|
|
99
|
+
},
|
|
96
100
|
},
|
|
97
101
|
|
|
98
102
|
watch: {
|
|
@@ -128,6 +132,24 @@ export default {
|
|
|
128
132
|
this.$emit("page-jump", this.elementTop, 0);
|
|
129
133
|
}
|
|
130
134
|
},
|
|
135
|
+
/**
|
|
136
|
+
* Scroll to the search result if the current one changes and it's on this page.
|
|
137
|
+
*/
|
|
138
|
+
currentSearchResultForPage(res) {
|
|
139
|
+
// skip page jump if the result is null (the current search result is not on this page)
|
|
140
|
+
if (!res) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
const y = this.getYForBbox(res); // y of the search result
|
|
144
|
+
const totalY = y + this.elementTop; // y of search result + page top
|
|
145
|
+
// skip page jump if the search result is already visible on this page
|
|
146
|
+
if (totalY < this.scrollBottom && totalY > this.scrollTop) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
this.$nextTick(function () {
|
|
150
|
+
this.scrollTo(y);
|
|
151
|
+
});
|
|
152
|
+
},
|
|
131
153
|
},
|
|
132
154
|
mounted() {
|
|
133
155
|
this.updateElementBounds();
|