Remove multiselect again and diy

This commit is contained in:
kolaente 2021-05-30 16:28:21 +02:00
parent 4692a1046d
commit acd1b9b83a
Signed by: konrad
GPG Key ID: F40E70337AB24C9B
3 changed files with 152 additions and 33 deletions

View File

@ -1,34 +1,51 @@
<template>
<modal v-if="active">
<div class="card p-4">
<multiselect
placeholder="What do you want to do?"
:search-results="results"
label="title"
@search="search"
:inline="true"
:show-empty="false"
@select="select"
:search-delay="0"
<modal v-if="active" class="quick-actions">
<div class="card">
<input
v-focus
class="input"
:class="{'is-loading': loading}"
v-model="query"
placeholder="Type a command or search..."
@keyup="search"
ref="searchInput"
@keydown.down.prevent="() => select(0, 0)"
/>
<div class="results">
<div v-for="(r, k) in results" :key="k" class="result">
<span class="result-title">
{{ r.title }}
</span>
<div class="result-items">
<button
v-for="(i, key) in r.items"
:key="key"
:ref="`result-${k}_${key}`"
@keydown.up.prevent="() => select(k, key - 1)"
@keydown.down.prevent="() => select(k, key + 1)"
@click.prevent.stop="() => doAction(r.type, i)"
@keyup.prevent.enter="() => doAction(r.type, i)"
>
{{ i.title }}
</button>
</div>
</div>
</div>
</div>
</modal>
</template>
<script>
import Multiselect from '@/components/input/multiselect'
import TaskService from '@/services/task'
const TYPE_LIST = 'list'
const TYPE_TASK = 'task'
const TYPE_ACTION = 'action'
const TYPE_TEAM = 'team'
export default {
name: 'quick-actions',
components: {
Multiselect,
},
data() {
return {
query: '',
@ -59,40 +76,59 @@ export default {
const lists = (Object.values(this.$store.state.lists).filter(l => {
return l.title.toLowerCase().includes(this.query.toLowerCase())
}) ?? [])
.map(l => {
l.type = TYPE_LIST
return l
})
const actions = this.availableActions
.filter(a => a.title.includes(this.query.toLowerCase()))
.map(a => {
a.type = TYPE_ACTION
return a
})
.filter(a => a.title.toLowerCase().includes(this.query.toLowerCase()))
return [...actions, ...lists, ...this.foundTasks, ...this.foundTeams]
return [
{
type: TYPE_ACTION,
title: 'Actions',
items: actions,
},
{
type: TYPE_TASK,
title: 'Tasks',
items: this.foundTasks,
},
{
type: TYPE_LIST,
title: 'Lists',
items: lists,
},
{
type: TYPE_TEAM,
title: 'Teams',
items: this.foundTeams,
},
].filter(i => i.items.length > 0)
},
nothing() {
return this.search === '' || Object.keys(this.results).length === 0
},
loading() {
return this.taskService.loading
},
},
created() {
this.taskService = new TaskService()
},
methods: {
search(query) {
this.query = query
this.searchTasks(query)
search() {
this.searchTasks()
},
searchTasks(query) {
searchTasks() {
if (this.query === '') {
return
}
if (this.taskSearchTimeout !== null) {
clearTimeout(this.taskSearchTimeout)
this.taskSearchTimeout = null
}
this.taskSearchTimeout = setTimeout(() => {
this.taskService.getAll({}, {s: query})
this.taskService.getAll({}, {s: this.query})
.then(r => {
r = r.map(t => {
t.type = TYPE_TASK
@ -102,8 +138,8 @@ export default {
})
}, 150)
},
select(e) {
switch (e.type) {
doAction(type, e) {
switch (type) {
case TYPE_LIST:
this.$router.push({name: 'list.index', params: {listId: e.id}})
break
@ -114,6 +150,35 @@ export default {
break
}
},
select(parentIndex, index) {
if (index < 0 && parentIndex === 0) {
this.$refs.searchInput.focus()
return
}
if (index < 0) {
parentIndex--;
index = this.results[parentIndex].items.length - 1
}
let elems = this.$refs[`result-${parentIndex}_${index}`]
if (this.results[parentIndex].items.length === index) {
elems = this.$refs[`result-${parentIndex + 1}_0`]
}
if (typeof elems === 'undefined' || elems.length === 0) {
return
}
if (Array.isArray(elems)) {
elems[0].focus()
return
}
elems.focus()
},
},
}
</script>

View File

@ -23,3 +23,4 @@
@import 'api-config';
@import 'datepicker';
@import 'notifications';
@import 'quick-actions';

View File

@ -0,0 +1,53 @@
.quick-actions {
.modal-content {
top: 6rem !important;
transform: translate(-50%, -3rem) !important;
}
.input {
border: 0;
font-size: 1.5rem;
}
.results {
text-align: left;
width: 100%;
color: $grey-800;
.result {
&-title {
background: $grey-50;
padding: .5rem;
display: block;
font-size: .75rem;
}
&-items {
button {
font-size: .9rem;
width: 100%;
background: transparent;
text-align: left;
box-shadow: none;
border-radius: 0;
text-transform: none;
font-family: $family-sans-serif;
font-weight: normal;
padding: .5rem .75rem;
border: none;
cursor: pointer;
&:focus, &:hover {
background: $grey-50;
box-shadow: none !important;
}
&:active {
background: $grey-100;
}
}
}
}
}
}