summaryrefslogtreecommitdiffstats
path: root/webapp
diff options
context:
space:
mode:
authorUdo Walter2019-01-15 05:48:12 +0100
committerUdo Walter2019-01-15 05:48:12 +0100
commit63bd8a3724480e2c38e45e7625714240063a15f1 (patch)
treee9f5e836520d25b83afbfa05bdca4c56c47d9704 /webapp
parent[webapp/datatable] Add ability to only show selected entries (diff)
downloadbas-63bd8a3724480e2c38e45e7625714240063a15f1.tar.gz
bas-63bd8a3724480e2c38e45e7625714240063a15f1.tar.xz
bas-63bd8a3724480e2c38e45e7625714240063a15f1.zip
[webapp/datatable] Add ability to select multiple rows with shift click
Diffstat (limited to 'webapp')
-rw-r--r--webapp/src/components/DataTable.vue78
1 files changed, 49 insertions, 29 deletions
diff --git a/webapp/src/components/DataTable.vue b/webapp/src/components/DataTable.vue
index 6f522f4..023760a 100644
--- a/webapp/src/components/DataTable.vue
+++ b/webapp/src/components/DataTable.vue
@@ -112,11 +112,12 @@
<v-divider></v-divider>
<RecycleScroller
- class="scroller"
+ class="scroller non-selectable"
:style="scrollerStyle"
:items="filterdRows"
:item-height="48"
:page-mode="rowCount <= 0"
+ @click.native.capture.passive="setShiftState"
>
<template slot="before-container">
<div class="table-head-wrapper non-selectable" :style="{ 'min-width': minWidth }">
@@ -145,16 +146,16 @@
<div v-else class="header-separator"></div>
</div>
</template>
- <div slot-scope="{ item }" class="table-row"
+ <div slot-scope="{ item, index }" class="table-row"
:style="item.selected && { backgroundColor: $vuetify.theme.primary + '11' }"
- @click="selectItem(item)"
+ @click="selectItem(item, index)"
@dblclick="$emit('dblclick', item.data)"
>
<div class="non-selectable">
- <v-icon style="cursor: pointer">{{ item.selected ? 'check_box' : 'check_box_outline_blank' }}</v-icon>
+ <v-icon style="cursor: pointer" :color="item.selected ? 'primary' : ''">{{ item.selected ? 'check_box' : 'check_box_outline_blank' }}</v-icon>
</div>
<div v-for="header in headers" :key="header.key" :style="{ width: header.width }" :class="{ 'auto-width': header.width === undefined }">
- <span v-if="$scopedSlots[header.key] === undefined" @dblclick.stop>{{ item.data[header.key] }}</span>
+ <span style="user-select: text" v-if="$scopedSlots[header.key] === undefined" @dblclick.stop>{{ item.data[header.key] }}</span>
<slot v-else :name="header.key" :item="item.data" />
</div>
</div>
@@ -194,10 +195,12 @@ export default {
search: [{ text: { raw: '', upper: '', regex: new RegExp(), regexCI: new RegExp() }, key: null }],
rowCount: 10,
selectState: 0,
+ headerSortState: {},
regex: false,
caseSensitive: false,
- headerSortState: {},
- onlyShowSelected: false
+ onlyShowSelected: false,
+ lastSelectIndex: null,
+ shiftKey: false
}
},
computed: {
@@ -269,48 +272,62 @@ export default {
}
},
filterdRows () {
+ this.lastSelectIndex = null
this.calcSelectState()
}
},
methods: {
- setShiftState (event) {
- this.shiftKey = event.shiftKey
- },
- selectItem (row) {
+ selectItem (row, index) {
+ // Select or deselect this row
const selected = row.selected = !row.selected
if (selected) {
this.selected.push(row.data)
+ // Shift click: Select all rows between this row and the last selected row
+ if (this.shiftKey && this.lastSelectIndex !== null) this.selectRows(index, this.lastSelectIndex)
} else {
this.selected.splice(this.selected.indexOf(row.data), 1)
+ // Shift click: Deselect all rows between this row and the last selected row
+ if (this.shiftKey && this.lastSelectIndex !== null) this.deselectRows(index, this.lastSelectIndex)
}
+ // Update variables and emit the new value
+ this.lastSelectIndex = index
this.calcSelectState()
this.$emit('input', this.selected)
},
toggleSelectAll () {
if (this.selectState <= 1) {
- this.filterdRows.forEach(row => {
- if (row.selected !== true) {
- row.selected = true
- this.selected.push(row.data)
- }
- })
+ this.selectRows(0, this.filterdRows.length)
} else {
- const tmpMap = {}
- this.filterdRows.forEach(row => {
- if (row.selected === true) {
- row.selected = false
- tmpMap[row.data.id] = true
- }
- })
- var newValue = []
- this.selected.forEach(item => {
- if (tmpMap[item.id] !== true) newValue.push(item)
- })
- this.selected = newValue
+ this.deselectRows(0, this.filterdRows.length)
}
+ // Update variables and emit the new value
this.calcSelectState()
this.$emit('input', this.selected)
},
+ selectRows (start, end) {
+ for (let i = Math.min(start, end); i <= Math.max(start, end); i++) {
+ let row = this.filterdRows[i]
+ if (row.selected !== true) {
+ row.selected = true
+ this.selected.push(row.data)
+ }
+ }
+ },
+ deselectRows (start, end) {
+ const deselected = {}
+ for (let i = Math.min(start, end); i <= Math.max(start, end); i++) {
+ let row = this.filterdRows[i]
+ if (row.selected === true) {
+ row.selected = false
+ deselected[row.data.id] = true
+ }
+ }
+ var newSelected = []
+ this.selected.forEach(item => {
+ if (deselected[item.id] !== true) newSelected.push(item)
+ })
+ this.selected = newSelected
+ },
calcSelectState () {
const displayedRows = this.filterdRows
var seenTrue = false
@@ -352,6 +369,9 @@ export default {
newSortState[header.key] = 'desc'
}
this.headerSortState = newSortState
+ },
+ setShiftState (event) {
+ this.shiftKey = event.shiftKey
}
}
}