summaryrefslogtreecommitdiffstats
path: root/webapp/src/components/DataTable.vue
diff options
context:
space:
mode:
authorUdo Walter2019-02-22 03:44:24 +0100
committerUdo Walter2019-02-22 03:44:24 +0100
commit3a95b5e8a9a030b318199838ac05a0692e5473a8 (patch)
tree97d1e67585b86dd205b86f853eeca8465ba43899 /webapp/src/components/DataTable.vue
parent[router] All modules have the new api style, deleted old unnecessary code (diff)
downloadbas-3a95b5e8a9a030b318199838ac05a0692e5473a8.tar.gz
bas-3a95b5e8a9a030b318199838ac05a0692e5473a8.tar.xz
bas-3a95b5e8a9a030b318199838ac05a0692e5473a8.zip
[webapp] implement time slicing loop and use it to search in the datatable
This improves UI responsiveness a lot while searching.
Diffstat (limited to 'webapp/src/components/DataTable.vue')
-rw-r--r--webapp/src/components/DataTable.vue90
1 files changed, 59 insertions, 31 deletions
diff --git a/webapp/src/components/DataTable.vue b/webapp/src/components/DataTable.vue
index 86aa789..037f689 100644
--- a/webapp/src/components/DataTable.vue
+++ b/webapp/src/components/DataTable.vue
@@ -8,6 +8,7 @@
"height": "Height",
"regex": "Regular Expressions",
"caseSensitive": "Case Sensitive",
+ "onlyShowSelected": "Only show selected entries.",
"selected": "selected"
},
"de": {
@@ -18,6 +19,7 @@
"height": "Höhe",
"regex": "Regulärer Ausdruck",
"caseSensitive": "Groß-/Kleinschreibung beachten",
+ "onlyShowSelected": "Nur ausgewählte Einträge anzeigen.",
"selected": "ausgewählt"
}
}
@@ -86,7 +88,7 @@
</div>
<div class="text-xs-center">
- {{ filterdRows.length + ' ' + $t('entries') + ' (' + selected.length + ' ' + $t('selected') + ')' }}
+ {{ filteredRows.length + ' ' + $t('entries') + ' (' + selected.length + ' ' + $t('selected') + ')' }}
</div>
<div class="text-xs-right">
@@ -114,7 +116,7 @@
<RecycleScroller
class="scroller non-selectable"
:style="scrollerStyle"
- :items="filterdRows"
+ :items="filteredRows"
:item-height="48"
:page-mode="rowCount <= 0"
@click.native.capture.passive="setShiftState"
@@ -159,7 +161,7 @@
<slot v-else :name="header.key" :item="item.data" />
</div>
</div>
- <div v-if="filterdRows.length === 0" slot="after-container" class="no-result">{{ $t('noResult') }}</div>
+ <div v-if="filteredRows.length === 0" slot="after-container" class="no-result">{{ $t('noResult') }}</div>
</RecycleScroller>
</div>
</template>
@@ -200,7 +202,9 @@ export default {
caseSensitive: false,
onlyShowSelected: false,
lastSelectIndex: null,
- shiftKey: false
+ shiftKey: false,
+ filteredRows: [],
+ filteringLoop: { breakLoop: false }
}
},
computed: {
@@ -209,7 +213,7 @@ export default {
},
scrollerStyle () {
const style = { '--min-table-width': this.minWidth }
- if (this.rowCount > 0) style.height = (Math.max(Math.min(this.rowCount, this.filterdRows.length), 1) * 48 + 58) + 'px'
+ if (this.rowCount > 0) style.height = (Math.max(Math.min(this.rowCount, this.filteredRows.length), 1) * 48 + 58) + 'px'
return style
},
dataKeys () { return this.headers.map(x => x.key) },
@@ -230,22 +234,6 @@ export default {
else if (this.regex && !this.caseSensitive) return (s, str) => s.text.regexCI.test(str)
else if (!this.regex && this.caseSensitive) return (s, str) => str.indexOf(s.text.raw) !== -1
else if (!this.regex && !this.caseSensitive) return (s, str) => str.toUpperCase().indexOf(s.text.upper) !== -1
- },
- filterdRows () {
- if (this.search.every(s => s.text.raw === '') && !this.onlyShowSelected) return this.sortedRows
- const onlySelected = this.onlyShowSelected
- const search = this.search
- const dataKeys = this.dataKeys
- const test = this.filterFunction
- return this.sortedRows.filter(row => (!onlySelected || (onlySelected && row.selected)) && search.every(s => {
- if (s.key === null) {
- return dataKeys.some(key => {
- return test(s, String(row.data[key]))
- })
- } else {
- return test(s, String(row.data[s.key]))
- }
- }))
}
},
watch: {
@@ -266,12 +254,21 @@ export default {
this.selected.push(row.data)
}
})
- this.calcSelectState()
+ if (this.filteredRows) this.calcSelectState()
this.$emit('input', this.selected)
}
}
},
- filterdRows () {
+ sortedRows () {
+ this.filterRows()
+ },
+ search: {
+ deep: true,
+ handler () {
+ this.filterRows()
+ }
+ },
+ filteredRows () {
this.lastSelectIndex = null
this.calcSelectState()
}
@@ -292,14 +289,15 @@ export default {
// Update variables and emit the new value
this.lastSelectIndex = index
this.calcSelectState()
+ this.$emit('click', row.data)
this.$emit('input', this.selected)
},
toggleSelectAll () {
- if (this.filterdRows.length === 0) return
+ if (this.filteredRows.length === 0) return
if (this.selectState <= 1) {
- this.selectRows(0, this.filterdRows.length - 1)
+ this.selectRows(0, this.filteredRows.length - 1)
} else {
- this.deselectRows(0, this.filterdRows.length - 1)
+ this.deselectRows(0, this.filteredRows.length - 1)
}
// Update variables and emit the new value
this.calcSelectState()
@@ -307,8 +305,8 @@ export default {
},
selectRows (start, end) {
var rows
- if (this.onlyShowSelected) rows = this.filterdRows.slice(0)
- else rows = this.filterdRows
+ if (this.onlyShowSelected) rows = this.filteredRows.slice(0)
+ else rows = this.filteredRows
for (let i = Math.min(start, end); i <= Math.max(start, end); i++) {
let row = rows[i]
if (row.selected !== true) {
@@ -319,8 +317,8 @@ export default {
},
deselectRows (start, end) {
var rows
- if (this.onlyShowSelected) rows = this.filterdRows.slice(0)
- else rows = this.filterdRows
+ if (this.onlyShowSelected) rows = this.filteredRows.slice(0)
+ else rows = this.filteredRows
const deselected = {}
for (let i = Math.min(start, end); i <= Math.max(start, end); i++) {
let row = rows[i]
@@ -336,7 +334,7 @@ export default {
this.selected = newSelected
},
calcSelectState () {
- const displayedRows = this.filterdRows
+ const displayedRows = this.filteredRows
var seenTrue = false
var seenFalse = false
for (let i = 0; i < displayedRows.length; i++) {
@@ -384,6 +382,36 @@ export default {
},
setShiftState (event) {
this.shiftKey = event.shiftKey
+ },
+ filterRows () {
+ if (this.search.every(s => s.text.raw === '') && !this.onlyShowSelected) this.filteredRows = this.sortedRows
+ const onlySelected = this.onlyShowSelected
+ const search = this.search
+ const dataKeys = this.dataKeys
+ const test = this.filterFunction
+ const rows = this.sortedRows
+
+ this.filteringLoop.breakLoop = true
+ const newFilteringLoop = { breakLoop: false }
+ this.filteringLoop = newFilteringLoop
+
+ const result = []
+ this.$loop(rows.length, 1000,
+ i => {
+ const row = rows[i]
+ if ((!onlySelected || (onlySelected && row.selected)) && search.every(s => {
+ if (s.key === null) {
+ return dataKeys.some(key => {
+ return test(s, String(row.data[key]))
+ })
+ } else {
+ return test(s, String(row.data[s.key]))
+ }
+ })) result.push(row)
+ },
+ () => newFilteringLoop.breakLoop,
+ () => { this.filteredRows = result }
+ )
}
}
}