Shift click & select all/none in index picker

This commit is contained in:
simon987 2021-11-12 10:12:25 -05:00
parent 030643cee0
commit e3f78fb693
3 changed files with 84 additions and 7 deletions

View File

@ -7,11 +7,28 @@
value-field="id"></b-form-select> value-field="id"></b-form-select>
</div> </div>
<div v-else> <div v-else>
<b-list-group id="index-picker-desktop">
<div class="d-flex justify-content-between align-content-center">
<span>
{{ selectedIndices.length }}
{{ selectedIndices.length === 1 ? $t("indexPicker.selectedIndex") : $t("indexPicker.selectedIndices") }}
</span>
<div>
<b-button variant="link" @click="selectAll()"> {{ $t("indexPicker.selectAll") }}</b-button>
<b-button variant="link" @click="selectNone()"> {{ $t("indexPicker.selectNone") }}</b-button>
</div>
</div>
<b-list-group id="index-picker-desktop" class="unselectable">
<b-list-group-item <b-list-group-item
v-for="idx in indices" v-for="idx in indices"
@click="toggleIndex(idx)" @click="toggleIndex(idx, $event)"
class="d-flex justify-content-between align-items-center list-group-item-action pointer"> @click.shift="shiftClick(idx, $event)"
class="d-flex justify-content-between align-items-center list-group-item-action pointer"
:class="{active: lastClickIndex === idx}"
>
<div class="d-flex"> <div class="d-flex">
<b-checkbox @change="toggleIndex(idx)" :checked="isSelected(idx)"></b-checkbox> <b-checkbox @change="toggleIndex(idx)" :checked="isSelected(idx)"></b-checkbox>
{{ idx.name }} {{ idx.name }}
@ -36,6 +53,7 @@ export default Vue.extend({
data() { data() {
return { return {
loading: true, loading: true,
lastClickIndex: null
} }
}, },
computed: { computed: {
@ -53,13 +71,50 @@ export default Vue.extend({
...mapActions({ ...mapActions({
setSelectedIndices: "setSelectedIndices" setSelectedIndices: "setSelectedIndices"
}), }),
shiftClick(index, e) {
if (this.lastClickIndex === null) {
return;
}
const select = this.isSelected(this.lastClickIndex);
let leftBoundary = this.indices.indexOf(this.lastClickIndex);
let rightBoundary = this.indices.indexOf(index);
if (rightBoundary < leftBoundary) {
let tmp = leftBoundary;
leftBoundary = rightBoundary;
rightBoundary = tmp;
}
for (let i = leftBoundary; i <= rightBoundary; i++) {
if (select) {
if (!this.isSelected(this.indices[i])) {
this.setSelectedIndices([this.indices[i], ...this.selectedIndices]);
}
} else {
this.setSelectedIndices(this.selectedIndices.filter(idx => idx !== this.indices[i]));
}
}
},
selectAll() {
this.setSelectedIndices(this.indices);
},
selectNone() {
this.setSelectedIndices([]);
},
onSelect(value) { onSelect(value) {
this.setSelectedIndices(this.indices.filter(idx => value.includes(idx.id))); this.setSelectedIndices(this.indices.filter(idx => value.includes(idx.id)));
}, },
formatIdxDate(timestamp: number): string { formatIdxDate(timestamp: number): string {
return format(new Date(timestamp * 1000), "yyyy-MM-dd"); return format(new Date(timestamp * 1000), "yyyy-MM-dd");
}, },
toggleIndex(index) { toggleIndex(index, e) {
if (e.shiftKey) {
return;
}
this.lastClickIndex = index;
if (this.isSelected(index)) { if (this.isSelected(index)) {
this.setSelectedIndices(this.selectedIndices.filter(idx => idx.id != index.id)); this.setSelectedIndices(this.selectedIndices.filter(idx => idx.id != index.id));
} else { } else {
@ -92,4 +147,21 @@ export default Vue.extend({
overflow-y: auto; overflow-y: auto;
max-height: 132px; max-height: 132px;
} }
.btn-link:focus {
box-shadow: none;
}
.unselectable {
user-select: none;
-ms-user-select: none;
-moz-user-select: none;
-webkit-user-select: none;
}
.list-group-item.active {
z-index: 2;
background-color: inherit;
color: inherit;
}
</style> </style>

View File

@ -23,7 +23,7 @@
<script lang="ts"> <script lang="ts">
import {EsResult} from "@/Sist2Api"; import {EsResult} from "@/Sist2Api";
import Vue from "vue"; import Vue from "vue";
import {humanFileSize, humanTime} from "@/util"; import {humanFileSize} from "@/util";
import DisplayModeToggle from "@/components/DisplayModeToggle.vue"; import DisplayModeToggle from "@/components/DisplayModeToggle.vue";
import SortSelect from "@/components/SortSelect.vue"; import SortSelect from "@/components/SortSelect.vue";

View File

@ -131,7 +131,6 @@ export default {
saveTagModalTitle: "Add tag", saveTagModalTitle: "Add tag",
saveTagPlaceholder: "Tag name", saveTagPlaceholder: "Tag name",
confirm: "Confirm", confirm: "Confirm",
indexPickerPlaceholder: "Select indices",
sort: { sort: {
relevance: "Relevance", relevance: "Relevance",
dateAsc: "Date (Older first)", dateAsc: "Date (Older first)",
@ -145,7 +144,13 @@ export default {
mimeSize: "Size distribution by media type", mimeSize: "Size distribution by media type",
dateHistogram: "File modification time distribution", dateHistogram: "File modification time distribution",
sizeHistogram: "File size distribution", sizeHistogram: "File size distribution",
} },
indexPicker: {
selectNone: "Select None",
selectAll: "Select All",
selectedIndex: "selected index",
selectedIndices: "selected indices",
},
}, },
fr: { fr: {
searchBar: { searchBar: {